2007-11-25

高鐵初體驗

今天要參加同學的婚禮,而在早先一周前上網預訂,台鐵車票已經被預訂一空啦...

而又不考慮國道客運,因為跟我要到達的地點相差頗多的

所以打算趁這次機會來體驗一下高速鐵路迷人的300km/h啦...

去程在高雄出發,預期應該可以買到自由座位,但是又怕是周六人潮多

所以再出發前一晚我已經又失眠啦,怕錯過預定搭乘的班次,敢不上中午的喜宴

今天七點就被鬧鐘叫醒了,是這個月以來最早的一次,除了熬夜沒睡覺之外..XD

被鬧鐘叫醒後,"即刻"、"火速"從床上跳起來,把前一天整理好的物品帶著就走啦

結果到了高鐵站,才發現時間還在太早了,離發車時間還有50min...囧....(我太緊張了!!!)

到7-11隨便買個東西吃早點,之後就是到處在高鐵裡面晃

(我忘記拍高鐵站的外觀了...我忘記了...我忘記了....太緊張怕錯過班次...就忘了...Orz)

高鐵站內到處都可以見到 $ONY砸大錢的廣告,然後想一想我的VAIO........

好像是我們愛用者在捐錢給$ONY買廣告.. = =



高雄站的空間感很棒,讓人很輕鬆沒有壓力,各種標示也很清楚,該往哪邊走一目了然

相對於對面的台鐵,呃!!!還是別提了



我即將搭乘的北上0110列車。 我果然是太早來了,拍這張相片時,才剛從台北發車而已



第一次買自由席



這個鎮站之寶的古鐘不能不拍一下的啦!!



興建中的迷樣建築物



到樓下晃晃



自從新增自由席之後,發車頻率增加不少
但是旅客人數好像也沒有多多少,今天是周六早上,自由席還是很多空位
所以大家不用急著訂票哩.買自由席就可以了



這班列車從車站出發了,加速加速..SPEED UPUP!!!



列車和月台的間隙很小,讓人看起來很舒服



剛好進站的兩台列車,被上面的列車長發現我在拍照..XD
而且進站停靠位子都很準確.真厲害.開門處即是排隊候車線



列車頭上的迷樣污垢 鳥撞擊後的血? 昆蟲屍體? 我猜是後者



候車區的椅子,設計簡單大方實用好看




這大家一定都知道,我承認我很無聊



今天的行程啦!!!
GO.GO.GO!!



住在高雄的網友應該不陌生吧,高鐵高度高,視野好,讚啦
speed up~up~~~加速中


以前都沒看過裡面是長甚麼樣子的



高速公路



過沒多久速度就飆到270km/h啦~~~~



不需要用生命騎GSX-R1300 隼...也可以達到最安全的地表最速喔!

感動感動..加分加分阿....

-----------婚禮過程與相片省略-------------

最近都在寫Paper..blog文章的遣詞用字越來越不口語了....哈哈

2007-11-18

11 phenomenal images of earth

原文出處: http://deputy-dog.com/2007/11/01/11-phenomenal-images-of-earth/


下載原始圖片 sources: 1, 2, 3, 4, 5, 6, 7

below are 11 incredible photos taken from space which illustrate just a few of earth’s fascinating geographical features and nature’s frightening unpredictability.

click on all pictures for humongous versions.

1. sri lankan coast, 26th december 2004

(above) the ocean rapidly retreats 400 metres on the south-western coast of sri lanka, just 5 minutes prior to the arrival of a devastating tsunami.

(above) the swirling waters continue to batter the coast just moments after the main wall of water has hit.

2. an alluvial fan, xinjiang province, china

(above) covering an area 56.6 x 61.3 km and taken on may 2nd, 2002, this photo shows an alluvial fan that formed on the southern border of the taklimakan desert in china. an alluvial fan usually forms as water leaves a canyon, each new stream eventually closing up due to sediment - the result being a triangle of active and inactive channels. the blue ones on the left are currently active.

3. retreating glaciers in the bhutan-himalaya

(above) a beautiful but clear sign that glaciers are slowly melting due to global warming. easily visible are the ends of most of these glacial valleys’ surfaces turning to water to form lakes, a trend which has been noticed only in the last few decades.

4. hurricane isabel, 2003

(above) this terrifying photo of hurricane isabel was taken on the international space station in 2003 and illustrates the immense size of the hurricane’s eye. this particular hurricane was the deadliest of 2003 and winds reached 165 mph at its peak.

5. greenland’s eastern coast, august 21st, 2003

(above) the fractal coastline of greenland and its numerous fjords as seen from space.

‘little spots of white in the water seem to be ice originating from the deeper fjords that reach all the way to the icecap covering most of the island.’ link

6. aurora borealis

(above) an astounding and spooky photo of the natural phenomenon known as aurora borealis, taken on-board space shuttle atlantis during the sts-117 mission.

7. a total solar eclipse from space, 1999

(above) the shadow of the moon covers part of earth on august 11th, 1999 in this photo taken from mir space station. this shadow raced across earth at 2000 km/h, all areas under the centre of it plunged into darkness during a total solar eclipse. this was apparently one the final photos taken from mir.

8. egmont national park, new zealand

(above) mt. egmont volcano last erupted in 1755 and is now situated at the centre of egmont national park. park regulations have ensured the survival of a forest which extends at a 9.5 km radius from the summit of the volcano, the result of which can be seen from space in the form of huge dark green disc. this photo was taken during the sts-110 mission, april 2002.

9. mt. etna eruption, october 2001

(above) taken from the international space station in 2001, this is a photo of a particularly violent eruption on the island of sicily which produced a cloud of ash that travelled as far as libya. on the humongous version of the photo lighter coloured smoke can be seen near the volcano - this was caused by lava igniting nearby forests.

10. richat structure, mauritania

(above) the cause of the richat structure in the sahara desert of mauritania has been debated for many years. at first it was thought to be a meteor impact crater due to its circularity but this has since been disproven due to the lack of shock-altered rock in its vicinity. this massive (30 mile diameter) oddity is now believed to have been a rock dome sculpted over time by erosion. this incredible image was taken by the advanced spaceborne thermal emission and reflection radiometer (aster) on october 7th, 2000.

2007-11-05

Regular Expression的表示法說明

原文來源

Regular Expression的表示法說明

  • Regular Expression 的表示字串的內容主要可以分成兩大類:
    1. Characters:一般字元(文數字元),所代表的意義與原字面的意義相同。
    2. Operators:特殊字元(非文數字字元),代表某種特殊規則的意義。若要取消其代表意義,必須使用「\」跳脫字元。
  • 例如:
    1. "foo" 的 RE 表示字串 "foo" 的意思。
    2. "[Ff]oo" 的 RE 表示字串 "Foo" 或字串 "foo" 的意思。
    3. "F*"的 RE 表示F這個字元會出現0次或多次。
    4. "F\*"的 RE 表示字串 "F*"的意思。

RE 的特殊字元-1

  • 「.」句號(period) 代表任意一個字元,如 /.at/ 可符合 bat, cat, rat等任何字開頭,結尾是at的單字。
  • 「^」(carat),表示位置在開頭,如 /^Mary/ ,代表以 Mary 開頭。
  • 「$」(dollor-sign),表示位置在結尾,如 /Mary$/ ,代表以 Mary 結尾。
  • 「[ ]」中括號(brackets)代表集合中的任一字元,如/[01256]/ 代表0,1,2,5,6這個集合中的任何一個字元。
  • 「-」連字號(dash)在中括號內表示「範圍」,如/[0-9]/代表0到9的任一個單一的數字。
  • 「^」(carat)在中括號內表示「否定」,/[^aeiou]/ 代表除了a,e,i,o,u這幾個母音之外的字元。

RE的特殊字元-2

  • 「|」(pipe)表示可選擇的,如/cat|dog|bird/代表cat, dog, bird 其中之一皆可(or的概念)。
  • 「?」問號(question mark) 表示前面的字元或集合出現0次或1次,如/colou?r / 代表u這個字可出現也可不出現。
  • 「+」加號(plus) 表示前面的字元或集合出現1次或多次,如/ap+le / 代表p這個字至少出現1次。
  • 「*」星號(asterisk)表示前面的字元或集合出現0次或多次,如/section [0-9]*/ 代表數字可出現也可不出現。
  • 「{}」大括號(curly-braces)表示前面的字元或集合出現的次數,如/c{5,8} / 代表c這個字重複出現5到8次。
----另外有人整理出下面這些.可以參考看看--- from: http://www.brad.tw/regularexpressions
  • 描述出組成字串的元素
    • 直接列出字元
    • [] : 字元集合任取一個元素.
      • [ - ] : 字元的範圍區間
      • [^ ] : 字元集合之反集合任取一個元素.
    • . : 表示任一字元
    • * : 表示前一個字元或是前一個RE出現 0 或多次
    • ? : 表示前一個字元或是前一個RE出現 0 或 1 次 (延伸)
    • + : 表示前一個字元或是前一個RE出現 1 或 多次 (延伸)
    • \{n\} : 表示前一個字元或是前一個RE出現 n 次 (延伸)
    • \{n,m\} : 表示前一個字元或是前一個RE出現 n 到 m 次 (延伸)
    • \{n,\} : 表示前一個字元或是前一個RE至少出現 n 次 (延伸)
    • \<word\> : 表示一個英文字, 凡是以 tab, 逗點, 據點等標點符號, 空白字原所分開的英文字為單位.
    • \<word: 表示一個英文字, 字首為 word.
    • word\>: 表示一個英文字, 字尾為 word.
    • word: 表示一個元素, 通常搭配後面表示法使用 (延伸)
    • | : 或, 兩個元素其中一個皆可 (延伸)
      • egrep '^(Linux|Windows)' test2
      • egrep -v '^#|^$' /etc/squid/squid.conf
  • 描述字串出現的位置
    • ^ : 每列的列首位置
    • $ : 每列的列尾位置
  • Escape Character 跳脫字元(\), 表示其後的特殊符號視作普通文字
  • ^^ : 表示 ^ 字元
  • $$ : 表示 $ 字元

[轉載]Regular Expression 教學

文章原始出處
作者 : hkln(HKLN.net)


[分享] Regular Expression 新手入門

Regular Expression (正規表示式,簡寫 regexp或regex)
是一個字串,可用來描述字串的模式,
例如我要表達「兩個英文大寫字母」,那麼 regexp 就是 [A-Z]{2}。
而使用這個 regexp ,就可以在一個字串內找出配合 (Match) 的部份,
例如在字串 $st = '11AA22BB33' 內,有哪些部份配合「兩個英文大寫字母」這個模式?
就會找到 'AA' 和 'BB' 兩部份了。

以下是一些常見的 regexp 應用:

use strict;
my ($st, $pattern, $replacement, @array, @matches);

##
## 有沒有找到至少一個 Match?
##
$st = '11AA22';
$pattern = 'AA';

if ($st =~ /$pattern/) {
print "has at least one match\n";
} else {
print "no match\n";
}


##
## 找出所有 Matches
##
$st = '11AA22BB33';
$pattern = '[A-Z]{2}';

@matches = $st =~ /$pattern/g;

foreach my $i (0 .. $#matches) {
print "$i : $matches[$i]\n";
}


##
## 找出所有 Matches,並取代它們
##
$st = '11AA22AA33';
$pattern = 'AA';
$replacement = 'XX';

$st =~ s/$pattern/$replacement/g;

print "$st\n";


##
## 在 Matches 的位置分割
##
$st = '11AA22AA33';
$pattern = 'AA';

@array = split /$pattern/, $st;

print join ',', @array;



以下是 .Net 例子(以 C# 語言)

using System;
using System.Text.RegularExpressions;

class MainClass
{
public static void Main(string[] args)
{
string st, pattern, replacement;
string[] array;
MatchCollection mc;

//
// has at least one match?
//
st = "11AA22";
pattern = @"AA";

if ( Regex.IsMatch(st, pattern) ) {
Console.WriteLine("has at least one match");
} else {
Console.WriteLine("no match");
}

//
// get all matches
//
st = "11AA22BB33";
pattern = @"[A-Z]{2}";

mc = Regex.Matches(st, pattern);

for (int i = 0; i < mc.Count; i++ )
{
Console.WriteLine("{0} : {1}", i, mc[i]);
}
//
// search and replace
//
st = "11AA22AA33"; pattern = @"AA"; replacement = "XX";
st = Regex.Replace(st, pattern, replacement);
Console.WriteLine("{0}", st);
//
// split
//
st = "11AA22AA33"; pattern = "AA";
array = Regex.Split(st, pattern);
Console.WriteLine(String.Join(",", array));
}
}


[[解釋 regexp 的意思]]
當您遇到一些很難看得懂的 regexp, 您可以用 YAPE::Regex::Explain 模組, 把 regexp 翻譯成英文,這對新手來說有很大幫助。

#### use YAPE::Regex::Explain;
my $pattern = '[A-Z]{2}';
print YAPE::Regex::Explain->new($pattern)->explain;
####

輸出結果:
[A-Z]{2} any character of: 'A' to 'Z' (2 times)
意思是「任何一個由 'A' 至 'Z' 的字元(兩次)」,
那麼它配合的東西就是:
AA
AB
...
AZ
BA
BB
...
ZA
ZB
...
ZZ
------------------------------------------------------------------------------------------------

>我目前所碰到的瓶頸是
>有沒有可能使用Regular Expression來判斷輸入的是數字,並且限定其數值範圍0.0

參考 perlretut 內的 "Building a regexp" 一節

------------------------------------------------------------------------------------------------

[[ 特殊字元 (Metacharacter) ]]

當您要表示一些特殊字元,例如括號,那就不能直接寫:
$pattern = '(';

而要在前面加上反斜號:
$pattern = '\(';

以下 regexp 的特殊字元:

{}[]()^$.|*+?/

為什麼這些是特殊字元呢?本文稍後會介紹。

例:
####
$st = '11((22';
$pattern = '\(\(';

@matches = $st =~ /$pattern/g;

foreach my $i (0 .. $#matches) {
print "$i : $matches[$i]\n";
}
####

順帶一提,應儘量用單引號來括字串,
因為它不會好像雙引號那樣會做字串插入,如果寫:
$pattern = "\(\(";

那結果變成:
$pattern = '((';

------------------------------------------------------------------------------------------------

[[ 脫離序列 (Escape Sequence) ]]

當您要表示 tab、 newline 等不能列印的字元,
可以用 Escape Sequence。

例:
$st = "11\t22\t33";
$pattern = '\t';

------------------------------------------------------------------------------------------------

[[ 字元類別 (Character Class) ]]

您除了可以表示一個固定的字元外,如
$pattern = 'A';

還可以表示一個字元集合,例如您想表示
「'A'字元或者'B'字元或者'C'字元」,可以寫
$pattern = '[ABC]';

即把您想 match 的字元寫在中括號內。

例:
$st = '11A22B33C44D';
$pattern = '[ABC]';

會找到以下的 match:
0 : A
1 : B
2 : C

例如您想找 'AAAXX' 或者 'AABXX' 或者 'AACXX':

$st = '11AACXX22AABXX33AAAXX44AAD';
$pattern = 'AA[ABC]XX';

會找到以下的 match:

0 : AACXX
1 : AABXX
2 : AAAXX

留意一點,雖然 $pattern 內的 [ABC] 是先寫A,
但結果是先找到 'AACXX',而不是'AAAXX',
因為 Perl 是先從 $st 的左邊開始找,而不是先從右邊開始找,
而 'AACXX' 是最左邊的 match。

------------------------------------------------------------------------------------------------

[[ 字元類別 - 脫離序列 ]]

在字元類別內表示一些特殊字元,也是要加反斜號,
不過字元類別內的特殊字元是:
-]\^$


本文稍後會解釋為何它們是特殊字元。

例:
$st = '11A22B33-44]';
$pattern = '[AB\-\]]';

會找到以下的 match:
0 : A
1 : B
2 : -
3 : ]

------------------------------------------------------------------------------------------------

[[ 字元類別 - 範圍運算子 (Range Operator) ]]

您可以用減號,來表示一段字元範圍,例如
$pattern = '[ABCDEFGHIJ]';

可以寫成
$pattern = '[A-J]';

這樣就更簡潔了。又例如
$pattern = '[ABCDKLMN0123]';

可以寫成
$pattern = '[A-DK-N0-3]';

但如果把減號寫在最頭或者最尾,例如
$pattern = '[-AB]';

$pattern = '[AB-]';

那麼減號就直接表示 '-' 字元,而不是範圍運算子了。

例:
$st = '99A88L773]';
$pattern = '[A-DK-N0-3]';

會找到以下的 match:
0 : A
1 : L
2 : 3


------------------------------------------------------------------------------------------------

[[ 字元類別 - 反相字元類別 (Negated Character Class) ]]

例如要表示「'A'或者'B'或者'C'」,就寫
$pattern = '[ABC]';

但如果要表示「'A'或者'B'或者'C'」的相反,即「不是'A'並且不是'B'並且不是'C'」
就可以寫
$pattern = '[^ABC]';

在字元類別內,如果第一個字元是 '^',就表示這是一個「反相字元類別」。

例:
$st = '11A22B33X44Y';
$pattern = '[^A-C0-9]';

會找到以下的 match:
0 : X
1 : Y

------------------------------------------------------------------------------------------------

[[ 字元類別 - 簡寫 ]]

Perl 提供了一些常用的字元類別簡寫,例如
$pattern = '[0-9]';

其實可以寫成
$pattern = '\d';

這就更簡潔了。以下列出這些簡寫:

\d 等於寫 [0-9]
\D 等於寫 [^0-9] ,即 \d 的相反
\w 等於寫 [0-9a-zA-Z_] ,即數字、英文大小寫字母和底線
\W 等於寫 [^0-9a-zA-Z_] ,即 \w 的相反
\s 等於寫 [\ \t\n\r\f] ,即白格字元 (Whitespace character),
包括space, tab, newline, carriage return, form feed

\S 等於寫 [^\ \t\n\r\f] ,即 \s 的相反

還有一個很特別的簡寫,就是點號 '.',
因為它比較複雜,所以稍後再介紹它。

例:
$st = '11A22b33_44=';
$pattern = '\D';

會找到以下的 match:
0 : A
1 : b
2 : _
3 : =


例:
$st = '11AA22A_33A044AX';
$pattern = 'A[^\dX-Z]';

會找到以下的 match:
0 : AA
1 : A_

------------------------------------------------------------------------------------------------

[[ Alternation ]]

如果想表示「'AB'字串或'KLM'字串或者'PQRST'」,可以寫
$pattern = 'AB|KLM|PQRST';
即用直線分隔它們。

Alternation 跟 Character Class 很像,
例如以下兩者是一樣的:

$pattern = '[ABC]';
$pattern = 'A|B|C';

不過 Character Class 不能表示超過一個字元的字串。

例:
$st = '11AB22KLMN33PQRS';
$pattern = 'AB|KLM|PQRST';

會找到以下的 match:
0 : AB
1 : KLM

如果寫:
$pattern = 'PQRST|KLM|AB';

那還是會先找到 'AB',效果跟 Character Class 一樣。

------------------------------------------------------------------------------------------------

[[群組 (Group)]]

如果想表示「'ABC'或者'ABKL'或者'ABPQR'」,除了可以寫:
$pattern = 'ABC|ABKL|ABPQR';

還可以這樣寫:
$pattern = 'AB(C|KL|PQR)';

即用括號來分開'AB'和接著的那三個 Alternatives,
好像數學上把 2*3 + 2*4 + 2*5 寫成 2 * (3+4+5)。

如果想連'AB'都要 match:
$pattern = 'AB|ABC|ABKL|ABPQR';

也可以把空字串都寫到括號內:
$pattern = 'AB(C|KL|PQR|)';

------------------------------------------------------------------------------------------------

[[群組 - 特殊變數 $1, $2, ...]]

括號還有一種特別的功能,就是把括號內 match 到的部份
放到特殊變數 $1, $2, ...。

例如您想檢查某字串是含有時間的模式,例如 HH:MM:SS,
(不檢查數值範圍),同時想取得時分秒各個部份,可以寫:

####
my ($time_string, $hour, $minute, $second);

$time_string = '12:34:56';
$pattern = '(\d\d):(\d\d):(\d\d)';

if ($time_string =~ /$pattern/) {
($hour, $minute, $second) = ($1, $2, $3);
print "hour=$hour,minute=$minute,second=$second";
} else {
print 'Invalid time format';
}

####

執行結果:
hour=12,minute=34,second=56


至於哪部份是 $1, $2, ...,就以開括號出現的先後順序來決定,
例如括著「時」那個開括號是第一個出現的,所以它就對應 $1。

(\d\d):(\d\d):(\d\d)
1______2______3

------------------------------------------------------------------------------------------------

[[群組 - 巢狀群組]]

括號內也可以有括號,成為巢狀群組,例如:

(\d\d):((\d\d):(\d\d))
1______23______4

####
my ($time_string, $hour, $minute, $second);

$time_string = '12:34:56';
$pattern = '(\d\d):((\d\d):(\d\d))';

if ($time_string =~ /$pattern/) {
print "\$1=$1\n\$2=$2\n\$3=$3\n\$4=$4";
} else {
print 'Invalid time format';
}
####

執行結果:
$1=12
$2=34:56
$3=34
$4=56

------------------------------------------------------------------------------------------------

[[群組 - 返回參照 (Backreferences) \1, \2, ...]]


跟 $1, $2, ... 有很密切關係的東西,就是 Backreferences,
即 \1, \2, ... 。

它們不同之處,在於 $1 只應該用在 regexp 「以外」,
而 \1 只應該用在 regexp 「以內」。

例:
####
$st = 'A_A';
$pattern = '([ABC])_\1';

if ($st =~ /$pattern/) {
print "\$1=$1";
}
####

執行結果:
$1=A


您可以嘗試把 $st 改成:
$st = 'B_B';
$st = 'C_C';

您會發現 \1 能夠取得之前所 match 的東西,
即應該放到 $1 的值。但要緊記,不應該在 regexp 以內寫 $1。


例:
####
$st = 'ALZ_A_L_Z';
$pattern = '([ABC])([KLM])([XYZ])_\1_\2_\3';

if ($st =~ /$pattern/) {
print "\$1=$1\n\$2=$2\n\$3=$3";
}
####

執行結果:
$1=A
$2=L
$3=Z

------------------------------------------------------------------------------------------------

[[ 群組 - $1, $2, ... 的開始和結束位置 ]]

Perl 5.6.0 提供了兩個陣列 @- 和 @+,
@- 儲存了 $1, $2, ... 的開始位置,@+ 就儲存結束位置。

例:
####
my ($time_string, $hour, $minute, $second);

$time_string = '12:34:56';
$pattern = '(\d\d):(\d\d):(\d\d)';

$time_string =~ /$pattern/;

foreach my $i (1 .. $#-) {
print "Match $i='${$i}' at position ($-[$i] , $+[$i])\n";
}
####

執行結果:
Match 1='12' at position (0 , 2)
Match 2='34' at position (3 , 5)
Match 3='56' at position (6 , 8)

------------------------------------------------------------------------------------------------

[[ 群組 - $` 、 $& 和 $' ]]

如果 regexp 沒有寫括號,就沒有 $1, $2, ... 可用了,
但您仍然可以用 $& 來取得 match,$` 則取得 match 前面所有東西,
$' 取得 match 後面所有東西。


####
$st = '11AA22';
$pattern = 'AA';

$st =~ /$pattern/;

print "\$`=$`\n\$&=$&\n\$'=$'";
####

執行結果:
$`=11
$&=AA
$'=22


如果用 substr 來表示,那麼:

$` 是 substr( $st, 0, $-[0] )
$& 是 substr( $st, $-[0], $+[0] - $-[0] )
$' 是 substr( $st, $+[0] )

------------------------------------------------------------------------------------------------

[[ 重覆 (Repetition) ]]

如果想表示「五個 'A' 字元」,可以寫
$pattern = 'AAAAA';

也可以用量化詞 (Quantifier) ,寫成
$pattern = 'A{5}';

這樣就更清楚了。而量化詞可以寫在字元、字元類別或群組的後面。

例:
$st = '11AAA22AAAAA';
$pattern = 'A{5}';

------------------------------------------------------------------------------------------------

[[重覆 - 最多和最少]]

量化詞可分成兩類:
1) 最多配對(貪心的) Maximal Match (Greedy)
2) 最少配對(不貪心的) Minimal Match (Non-greedy)


以下列出「最多配對」:

A? 表示 0 個或 1 個 'A' 字元(以最多為準)
A* 表示 0 個或以上的 'A' 字元(以最多為準)
A+ 表示 1 個或以上的 'A' 字元(以最多為準)

A{n} 表示 n 個 'A' 字元
A{n,m} 表示最少 n 個,最多 m 個 'A' 字元(以最多為準)
A{n,} 表示最少 n 個 'A' 字元(以最多為準)

以下列出「最少配對」:

A?? 表示 0 個或 1 個 'A' 字元(以最少為準)
A*? 表示 0 個或以上的 'A' 字元(以最少為準)
A+? 表示 1 個或以上的 'A' 字元(以最少為準)

A{n}? 表示 n 個 'A' 字元
(這個其實沒有所謂的「最多」還是「最少」之分,
定義這個符號只是為了保持符號一致性而己)
A{n, m}? 表示最少 n 個,最多 m 個 'A' 字元(以最少為準)
A{n,}? 表示最少 n 個 'A' 字元(以最少為準)


到底「最多配對」和「最少配對」有什麼分別呢?例如

$st = 'AAAAA';
$pattern1 = 'A{3,5}'; # 最多配對
$pattern2 = 'A{3,5}?'; # 最少配對

那麼 match 可能是:
1) 'AAA'(字元位置0至2)
2) 'AAAA'(字元位置0至3)
3) 'AAAAA'(字元位置0至4)

如果是「最多配對」,那麼 match 就是 'AAAAA',因為它是最多次數,
如果是「最少配對」,那麼 match 就是 'AAA',因為它是最少次數。

------------------------------------------------------------------------------------------------

[[ 特點字元 - 任何一個字元 ]]

如果要表示「任何一個字元」,可以用點號 '.'。

在預設的情況下,它會配到「任何一個字元,除了 "\n" 之外」:

$st = "123ABC_!@\n";
$pattern = '.';

@matches = $st =~ /$pattern/g;

如果要配到「任何一個字元,包括 "\n"」,
就到加入 s 這個「修飾詞」(Modifier):

@matches = $st =~ /$pattern/sg;

s 的意思是「把字串當作單行 (Single Line)」。

------------------------------------------------------------------------------------------------

[[ 字串的開頭 ]]

如果要表示「字串的開頭」,可以用 '^',例如:

$st = 'AA22';
$pattern = '^AA';

@matches = $st =~ /$pattern/g;


執行結果:
0 : AA


但 match 當中不會有 '^' 所配出來的字元,
因為 '^' 主要用來測試字串的特性(例如字串位置),
而不是配任何字元的。

為了方便理解,您可以把它「想像」成一個看得見的字元,
例如:

$st = '頭AA22尾'; ## $st = 'AA22'
$pattern = '頭AA'; ## $pattern = '^AA';

------------------------------------------------------------------------------------------------

[[ 字串的結尾 ]]

如果要表示「字串的結尾,或者在字串最尾的 \n 和前面字元的中間」,
可以用 '$',例如:

$st = "AA\nBB\n"; ## 用了雙引號
$pattern = '$';

@matches = $st =~ /$pattern/g;

結果有兩個 match ,但是'$' 與 '^' 一樣,是不會配到字元的。
您可以把它想像成:

$st = "頭AA\nBB尾\n尾"; ## $st = "AA\nBB\n";
$pattern = '尾'; ## $pattern = '$';

另外,當檢查一個字串是否符合某種格式時,
通常會 '^' 和 '$' 一起用,
例如檢查某字串是否符合「三位數字」的格式:

####
$st = "123";
$pattern = '^\d{3}$';

if ($st =~ /$pattern/) {
print "Valid format";
} else {
print "Invalid format";
}
####

------------------------------------------------------------------------------------------------

[[ 多行 (Multi-line) ]]

一個字串內可以含有 \n,例如:

$st = "AA\nAA\nAA\n";
$pattern = '^AA';

如果我們想 '^' 配到每一行的開頭,
可以用 m 修飾詞:

@matches = $st =~ /$pattern/mg;

執行結果:
0 : AA
1 : AA
2 : AA


想像成:

$st = "頭AA尾\n頭AA尾\n頭AA尾\n尾";
$pattern = '頭AA';


用了 m 修飾詞,也會令 '$' 配到每一行的結尾,


$st = "AA\nAA\nAA\n";
$pattern = 'AA$';
@matches = $st =~ /$pattern/mg;


想像成:

$st = "頭AA尾\n頭AA尾\n頭AA尾\n尾";
$pattern = 'AA尾';

如果用了 m 修飾詞,您仍然可以用:

\A 表示沒有 m 修飾詞的 '^' 意思
\Z 表示沒有 m 修飾詞的 '$' 意思
\z 代表字串的結尾(即 \Z ,但不包括最尾 \n 和前面字元的中間)


$st = "AA\nAA\nAA\n";
$pattern1 = '\AAA';
$pattern2 = 'AA\Z';
$pattern3 = 'AA\z';


總括來說,s 修飾詞會影響 '.' 的意思,
m 修飾詞會影響 '^' 和 '$' 的意思,
s 和 m 總共有四種可能:

沒有 s 和 m :預設模式 (Default Mode)
/s :單行模式 (Single Line Mode)
/m :多行模式 (Multi-Line Mode)
/sm :清楚多行模式 (Clean Multi-Line Mode)


看看大家能否解釋以下程式的執行結果:

####
$st = "A\nA\nA\n";
$pattern = '(^|$|.)';

@matches = $st =~ /$pattern/smg;
####

------------------------------------------------------------------------------------------------

[[ 字的邊界 Word Boundary ]]

字的邊界是指兩個連續字元的中間,
一個會配到 \w,而另一個會配到 \W。
(字串的開頭和結尾也視為配到 \W)

例如:

$st = 'ABC-=+';
$pattern = 'C\b';

@matches = $st =~ /$pattern/g;

因為左邊的 'C' 會配到 \w,而右邊的 '-' 會配到 \W,
所以 \b 會配到它們的中間。

\b 不代表某個字元,而是代表某個位置的特性。
您可以想像成:

$st = '界ABC界-=+';
$pattern = 'C界';

您可以用 \B 來表示 \b 的相反,即「不是邊界」,

例如:

$st = 'ABCDE';
$pattern = '\BC\B';

@matches = $st =~ /$pattern/g;

因為 'C' 本身配到 \w ,而它左邊的'B'和右邊的'D'也是配到 \w,
所以沒有邊界。

------------------------------------------------------------------------------------------------

[[ 不分大小寫 (Case-insensitive) ]]

如果加入了 i 修飾詞,就會做不分大小寫的配對,
例如:

$st = '11AA22BB';
$pattern = '[abAB]';

@matches = $st =~ /$pattern/g;

可以用 i 修飾詞寫成:

$st = '11AA22BB';
$pattern = '[AB]'; # 或者 '[ab]'

@matches = $st =~ /$pattern/ig;

因為不分大小寫,所以不必在 $pattern 把大小寫都列出來了。

------------------------------------------------------------------------------------------------

[[ x 修飾詞 ]]

如果用了 x 修飾詞,就會令 regexp 解譯器忽略 $pattern 內的白格,
(除了那些在被反斜號標示了的白格,及那些在字元類別內的白格)
還有在 $pattern 內的 '#' 也會有好像 Perl 一樣的單行註解作用,
(除了那些在被反斜號標示了的'#',及那些在字元類別內的'#')

它的用途是讓您可以把 regexp 寫成容易閱讀的方式,及加入註解。
例子:


不用 x 修飾詞的寫法:

$st = '11AA22 33\\\\44##';
$pattern = '(A| |\\\\|#)';
@matches = $st =~ /$pattern/g;


用了 x 修飾詞的寫法:

$st = '11AA22 33\\\\44##';

$pattern = q{

( # 左括號表示 Alternation 開始
A # 'A' 字元
| # 或者
[ ] # 用字元類別表示空格
| # 或者
\\\\ # 反斜號字元
|
[#] # 用字元類別表示'#'
) # 右括號表示完結

};

@matches = $st =~ /$pattern/xg;

------------------------------------------------------------------------------------------------

[[ 伸展模式 (Extended Patterns) ]]

除了傳統的 regexp 語法外,Perl 還定義了一些額外的語法,
但在其它工具未必有這些語法,而且有些語法可能還在實驗階段,
說不定將來會被刪除,詳情請參閱說明文件。

這些語法都是這樣子的:

(?char)

而 char 就表示伸展的種類。

------------------------------------------------------------------------------------------------

[[ 伸展模式 - 內嵌註解 (Embedding Comments) ]]

語法:
(?#text)

在 text 位置的東西會當作註解,
但要留意 text 內不可以含有右括號。

例:
$pattern = '(?# THIS IS A COMMENT)(A| |\\\\|#)';

------------------------------------------------------------------------------------------------

[[ 伸展模式 - 非捕捉群組 (Non-capturing groupings) ]]

語法:
(?:pattern)

之前提到括號有個特別的作用,就是會把配到的東西放進 $1, $2,...,
例如:

$time_string = '12:34:56';
$pattern = '(\d\d):(\d\d):(\d\d)';

if ($time_string =~ /$pattern/) {
($hour, $minute, $second) = ($1, $2, $3);
print "hour=$hour,minute=$minute,second=$second";
}

但如果您不想放的話,可以用 (?:pattern):

$time_string = '12:34:56';
$pattern = '(\d\d):(?:\d\d):(\d\d)';

if ($time_string =~ /$pattern/) {
($hour, $minute, $second) = ($1, $2, $3);
print "hour=$hour,minute=$minute,second=$second";
}


因為「分」那部份使用了(?:pattern) ,所以就不會放到本來的 $2,
這就輪到「秒」的部份放到 $2了。

------------------------------------------------------------------------------------------------

[[ 伸展模式 - 內嵌修飾詞 (Embedded Modifiers) ]]

語法:
(?imsx-imsx:pattern)

之前提到可以用 i 修飾詞來做不分大小寫的配對,例如:

$st = '11AB22Ab33aB44ab';
$pattern = 'AB';

@matches = $st =~ /$pattern/ig;

這樣整個 $pattern 都是不分大小寫了,
如果想某部份分辨大小寫,某部份不分辨,
可以用內嵌的寫法。

$st = '11AB22Ab33aB44ab';
$pattern = '(?i:A)(?-i:B)';

@matches = $st =~ /$pattern/g;

表示 A 不分大小寫,B 就分辨大小寫。
如果修飾詞前面是減號,表示關閉該修飾詞,
例如 (?s-i),表示啟動 s 修飾詞,關閉 i 修飾詞。

其實內嵌修飾詞的語法,是在非捕捉群組內加入修飾詞而己。

------------------------------------------------------------------------------------------------

[[ 伸展模式 - 往前看(Look-ahead)和往後看(Look-behind) ]]

語法:
往前看(正)(Positive Look-ahead) (?=pattern)
往後看(正)(Positive Look-behind) (?<=pattern)
往前看(負)(Negative Look-ahead) (?!pattern)
往後看(負)(Negative Look-behind) (?
舉例來說:

$st = 'ABCDEFGH';
$pattern = '\w{2}';
@matches = $st =~ /$pattern/g;


執行結果:
0 : AB
1 : CD
2 : EF
3 : GH

您可以想像它是由左往右走,當配到一個match,
下一次就由match之後開始走:

ABCDEFGH
由A的位置開始走,配到 AB,剩下 CDEFGH ('AB')
由C的位置開始走,配到 CD,剩下 EFGH ('AB', 'CD')
由E的位置開始走,配到 EF,剩下 GH ('AB', 'CD', 'EF')
由G的位置開始走,配到 GH,剩下 ('AB', 'CD', 'EF', 'GH')


如果想在走路的時候,還要同時往前面看,
可以用「往前看」或「往後看」。
例如仍然要找出 \w{2},但同時要檢查它的前面(即右面)必須是\w{2},
可以寫:

$pattern = '\w{2}(?=\w{2})';

執行結果:
0 : AB
1 : CD
2 : EF


這裡的 (?=\w{2}) 用了「往前看(正)」,
這部份是不會配到任何字元,只是用來檢查字串的特性:

ABCDEFGH
由A的位置開始,配到AB,往前看到CD,剩下 CDEFGH ('AB')
由C的位置開始,配到CD,往前看到EF,剩下 EFGH ('AB', 'CD')
由E的位置開始,配到EF,往前看到GH,剩下 GH ('AB', 'CD', 'EF')
由G的位置開始,雖然GH 可以配到\w{2} ,但往前看不到 \w{2},所以沒有match
完結

同理,如果改用「往後看」:

$pattern = '(?<=\w{2})\w{2}';

執行結果:
0 : CD
1 : EF
2 : GH

ABCDEFGH
由A的位置開始,直至走到C的位置時,
才能夠往後看到 AB,配到CD,剩下 EFGH ('CD')
由E的位置開始,往後看到CD,配到EF,剩下 GH ('CD', 'EF')
由G的位置開始,往後看到EF,配到GH,剩下 ('CD', 'EF', 'GH')
完結


Negative Look-ahead 是 Positve Look-ahead的相反,
例如仍然要找出 \w{2},但同時要檢查它的前面必須「不是」\w{2},
可以寫:

$st = 'ABCDEFGH';
$pattern = '\w{2}(?!\w{2})';
@matches = $st =~ /$pattern/g;


執行結果:
0 : FG

因為 'FG'的右面只有 'H' ,即 \w ,而不是 \w{2},
所以配到。

2007-10-19

單車旅行 - 旗津

從上星期就和朋友計畫騎單車前往旗津了,今天天氣晴朗,溫度也很宜人
在前天睡眠品質不好,早上九點鐘爬起來到學校拍畢業大頭照
下午一點半,從楠梓火車站出發,目標前往旗津

--------------騎車過程---------------
(我沒帶相機,我沒帶相機,我沒帶相機,我沒帶相機,我沒帶相機)

從楠梓到渡輪站大約90~100分鐘,時速平均20km/h
路程約20km

旗津的踩風大道從旗津醫院那邊開始,經過過港隧道附近,最終到高字塔,一共有10km喔
因為順風的關係,今天踩風大道的去程很順暢,幾乎不太需要踩動就可以滑阿滑到底
但是回程......呃!!!....逆風..10km ( ̄口 ̄)!!.....速度只能維持在15km/h
<在踩風大道大約5km處,遇到一位媽媽和兒子在路邊修理車子,
 其中一台後齒輪卡進了不知名的橡膠帶,我是 ☑誠懇 ☑優質居家 ☑好人\( ̄▽ ̄)♂!
 看到這種事情,當然要見義勇為一下。
 今天做了件好事,感覺不錯,希望老天爺有看到,可以讓我早日完成論文>

建議有去旗津的朋友可以去逛逛完整的單車專屬的踩風大道,可以看到旗津不一樣的風景喔

後記:
旗津的烤小卷還是一樣好吃阿
<( ̄ c ̄)y▂ξ -------------------


今天總路程, 66.06 km (屁股痛>_<...下次要買車褲了)



今天兩罐水都喝光了,還好夠用,可以省下補給水費用




到海邊騎車,齒輪免不了都是沙子,回家之後又要清潔保養了



這是裝了碼表之後的累積路程.總共218.6km....

買碼表之前不知道騎了多少公里...XD