2012年9月30日 星期日

[ Perl 函數 ] substr : 子字串的切割


來源自 這裡
說明 :
我們可以利用函數 substr 來取出某個字串內的子字串, 透過不訂長度的參數提供客製化的功能; 甚至我們能透過它將特定位置的子字串以提供的字串進行取代.

語法 :
substr EXPR,OFFSET,LENGTH,REPLACEMENT
substr EXPR,OFFSET,LENGTH
* substr EXPR,OFFSET 

substr 會對參數 EXPR 進行處理.
- 如果只提供 OFFSET 參數, 則子字串的範圍從 OFFSET 的位置到字串結束; 如果 OFFSET 是負數, 則從字串尾端數回來.
- 如果提供 OFFSETLENGTH, 則從 OFFSET 的位置取長度為 LENGTH 的子字串; 如果 LENGTH 為負數, 說明從字串結尾往前數長度為 LENGTH 不要算進子字串.
- 如果提供 OFFSETLENGTHREPLACEMENT, 則將子字串以 REPLACEMENT 取代.

簡單範例如下 :
  1. my $s = "The black cat climbed the green tree";  
  2. my $color  = substr $s, 45;      # black  
  3. print "\$color=$color\n";  
  4.   
  5. my $middle = substr $s, 4, -11;    # black cat climbed the  
  6. print "\$middle=$middle\n";  
  7.   
  8. my $end    = substr $s, 14;        # climbed the green tree  
  9. print "\$end=$end\n";  
  10.   
  11. my $tail   = substr $s, -4;        # tree  
  12. print "\$tail=$tail\n";  
  13.   
  14. my $z      = substr $s, -42;     # tr  
  15. print "\$z=$z\n";  
使用範例 :
底下透過範例說明使用方法.

- Example 1a. Supply an expression and a positive offset value.
在這個範例將字串 $string 從 offset=4 的位置一直到字串結尾擷取到另一個變數 $fragment. 代碼如下:
  1. #!/usr/bin/perl  
  2. use strict;  
  3. use warnings;  
  4.   
  5. my $string = 'Now is the time for all good people to come to the aid of their party';  
  6. my $fragment =  substr $string, 4;  
  7. print "  string: <$string>\n";  
  8. print "fragment: <$fragment>\n";  
執行結果:
string: <Now is the time for all good people to come to the aid of their party>
fragment: 
<is the time for all good people to come to the aid of their party>

- Example 1b. Supply an expression and a positive offset value.
在這個範例中, 透過函數 index() 找到 'people' 所在位置, 並將之指定給 OFFSET. 如此我們可以取得從 'people' 算起一直到字串結束的子字串:
  1. #!/usr/bin/perl  
  2. use strict;  
  3. use warnings;  
  4.   
  5. # Find the location of the substring 'people'  
  6. my $string = 'Now is the time for all good people to come to the aid of their party';  
  7. my $fragment =  substr $string, index($string, 'people');  
  8. print "  string: <$string>\n";  
  9. print "fragment: <$fragment>\n";  
執行結果:
string: <Now is the time for all good people to come to the aid of their party>
fragment: 
<people to come to the aid of their party>

- Example 2a. Supply an expression, a positive offset value and a length
透過 LENGTH 參數, 我們可以決定子字串的長度. 下面從 OFFSET=7 的位置上取出長度為 8 的子字串:
  1. #!/usr/bin/perl  
  2. use strict;  
  3. use warnings;  
  4.   
  5. my $string = 'Now is the time for all good people to come to the aid of their party';  
  6. my $length = 8;  
  7. my $fragment =  substr $string, 7, $length;  
  8. print "  string: <$string>\n";  
  9. print "fragment: <$fragment>\n";  
執行結果:
string: <Now is the time for all good people to come to the aid of their party>
fragment: 
<the time>

- Example 2b. Supply an expression, a negative offset value and a length
如果我們的 OFFSET 是負數, 說明從字串結果從字串尾往回數. 下面代碼從結尾往回數 16 個位置的 offset 上取長度為 10 的子字串:
  1. #!/usr/bin/perl  
  2. use strict;  
  3. use warnings;  
  4.   
  5. my $string = 'Now is the time for all good people to come to the aid of their party';  
  6. my $length = 10;  
  7. my $fragment =  substr $string, -16, $length;  
  8. print "  string: <$string>\n";  
  9. print "fragment: <$fragment>\n";  
執行結果:
string: <Now is the time for all good people to come to the aid of their party>
fragment: 
<d of their>

- Example 2c. Supply an expression, a positive offset value and a negative length
如果參數 LENGTH 是負數, 說明有多少個長度從結尾的位置被 truncate 掉. 下面代碼取出從字串頭往前數 7 的到字串尾往回數 20 的子字串:
  1. #!/usr/bin/perl  
  2. use strict;  
  3. use warnings;  
  4.   
  5. my $string = 'Now is the time for all good people to come to the aid of their party';  
  6. my $length = -20;  
  7. my $fragment =  substr $string, 7, $length;  
  8. print "  string: <$string>\n";  
  9. print "fragment: <$fragment>\n";  
執行結果:
string: <Now is the time for all good people to come to the aid of their party>
fragment: 
<the time for all good people to come to th>

- Example 3. An expression, an offset value, a length and a replacement value
如果有提供 REPLACEMENT 參數, 則子字串會被該參數取代. 下面透過函數 index() 找到 'people' 所在位置並且 'people' 的長度為6. 接著我們使用 REPLACEMENT 參數 將 'people' 取代成 'men':
  1. #!/usr/bin/perl  
  2. use strict;  
  3. use warnings;  
  4.   
  5. my $string = 'Now is the time for all good people to come to the aid of their party';  
  6. my $fragment =  substr $string, index($string, 'people'), 6'men';  
  7. print "  string: <$string>\n";  
  8. print "fragment: <$fragment>\n";  
執行結果:
string: <Now is the time for all good men to come to the aid of their party>
fragment: 
<people>

可以看到原 $string 的 'people' 被替換成 'men', 而且 substr() 依舊返回 'people'.

- Example 4. Assigning to substr()
事實上 substr() 可以被當作 lvalue 使用, 所以你可以透過給定值給 substr() 取代 REPLACEMENT 的功能. 下面代碼將 'people' 子字串取代為 'women':
  1. #!/usr/bin/perl  
  2. use strict;  
  3. use warnings;  
  4.   
  5. my $string = 'Now is the time for all good people to come to the aid of their party';  
  6. substr($string, index($string, 'people'), 6) = 'women';  
  7. print "  string: <$string>\n";  
執行結果:
string: <Now is the time for all good women to come to the aid of their party>


補充說明 :
perl 學習手扎 > 第十二章 字串處理
perldoc.perl.org > functions > substr
stackoverflow > What are the uses of lvalue subroutines in Perl?
LValues are recommended to be avoided. They're fun and all, but they confuse new users who make assumptions about how all subs work, and thus it should be avoided in code when a better way is available...
This message was edited 24 times. Last update was at 01/10/2012 11:08:33

2012年9月26日 星期三

[ Perl 函數 ] split : 根據 Pattern 切割字串

來源自 這裡 
說明 : 
split 是 Perl 中非常有用的函式之一,它可以將一個字串分割並將之置於陣列中。若無特別的指定,該函式亦使用 RE 與 $_ 變數 

語法 : 
* split /PATTERN/,EXPR,LIMIT
* split /PATTERN/,EXPR
* split /PATTERN/

如果 PATTERN 有給, EXPR 預設是 $_; 如果 PATTERN 是空字串, 則 EXPR 會被切割成以字元為單位的陣列. 範例如下: 
  1. print join(':', split(''"abc"));  
輸出為 : 
a:b:c

使用範例 : 
底下為此函數的使用範例. 

- Example 1. Splitting by a special character 
對句子使用特定字元進行切割 : 
  1. #!/usr/bin/perl  
  2.   
  3.   use strict;  
  4.   use warnings;  
  5.   
  6.   my $data = 'Becky Alcorn,25,female,Melbourne';  
  7.   
  8.   my @values = split(',', $data);  
  9.   
  10.   foreach my $val (@values) {  
  11.     print "$val\n";  
  12.   }  
  13.   
  14.   exit 0;  
執行結果 : 
Becky Alcorn
25
female
Melbourne

- Example 2. Splitting by a string 
底下使用字串 '~~~' 進行切割 : 
  1. #!/usr/bin/perl  
  2.   
  3. use strict;  
  4. use warnings;  
  5.   
  6. my $data = 'Bob the Builder~~~10:30am~~~1,6~~~ABC';  
  7. my @values = split('~~~', $data);  
  8.   
  9. foreach my $val (@values)   
  10. {  
  11.     print "$val\n";  
  12. }  
  13.   
  14. exit 0;  
執行結果 : 
Bob the Builder
10:30am
1,6
ABC

- Example 3. Splitting on a pattern 
PATTERN 可以使用 RE 來定義更廣泛的 separator, 底下使用 "\\d+" 將所有不定長度的數字當作 separator: 
  1. #!/usr/bin/perl  
  2.   
  3. use strict;  
  4. use warnings;  
  5.   
  6. my $data = 'Home1Work2Cafe3Work4Home';  
  7.   
  8. # \d+ matches one or more integer numbers  
  9. my @values = split(/\d+/, $data);  
  10.   
  11. foreach my $val (@values)   
  12. {  
  13.     print "$val\n";  
  14. }  
  15. exit 0;  
執行結果 : 
Home
Work
Cafe
Work
Home

- Example 4. Splitting on an undefined value 
如果 PATTERN 為 undef, 則會將字串切割為字元的陣列: 
  1. #!/usr/bin/perl  
  2.   
  3. my $data = 'Becky Alcorn';  
  4.   
  5. my @values = split(undef,$data);  
  6.   
  7. foreach my $val (@values) {  
  8.     print "$val\n";  
  9. }  
  10.   
  11. exit 0;  
執行結果 : 
B
e
c
k
y

A
l
c
o
r
n

- Example 5. Splitting on a space 
如果你使用 ' ' 來進行切割, 會類似使用 RE 的 /\s+/. 包含斷行, Tab 都會被當作 separator: 
  1. #!/usr/bin/perl  
  2. use strict;  
  3. use warnings;  
  4.   
  5. my $data = "Becky\n\nAlcorn";  
  6. my @values = split(' ',$data);  
  7.   
  8. # Print 'aa' either side of the value, so we can see where it split  
  9. foreach my $val (@values) {  
  10.     print "aa${val}aa\n";  
  11. }  
  12. exit 0;  
執行結果 : 
aaBeckyaa
aaAlcornaa

如果你"真的"希望只用空白當作 separator, 可以考慮下面代碼: 
  1. my @values = split(/ /,$data);  
- Example 7. Split and context 
如果你沒有給任何參數, split 會對 $_ 使用 ' ' 當作 separator 進行切割: 
  1. #!/usr/bin/perl  
  2. use strict;  
  3. use warnings;  
  4.   
  5. foreach ("%%Bob\tthe Builder%%""%%Thomas\nthe TankEngine%%"'%%B1 and B2%%')   
  6. {  
  7.     my @values = split;  
  8.     print "Split $_:\n";  
  9.     foreach my $val (@values)   
  10.     {  
  11.         print "--$val\n";  
  12.     }  
  13. }    
  14.   
  15. exit 0;  
執行結果: 
Split %%Bob the Builder%%:
--%%Bob
--the
--Builder%%
Split %%Thomas
the TankEngine%%:
--%%Thomas
--the
--TankEngine%%
Split %%B1 and B2%%:
--%%B1
--and
--B2%%

- Example 8. Limiting the split 
你也可以透過 LIMIT 參數決定最多切出多少個單位 (LIMIT=2 意味只切一次.), 下面代碼最多只會切割 2 次: 
  1. #!/usr/bin/perl  
  2. use strict;  
  3. use warnings;  
  4.   
  5. my $data = 'Becky Alcorn,25,female,Melbourne';  
  6.   
  7. my @values = split(',', $data, 3);  
  8.   
  9. foreach my $val (@values)   
  10. {  
  11.     print "$val\n";  
  12. }  
  13. exit 0;  
執行結果: 
Becky Alcorn
25
female,Melbourne

- Example 9. Keeping the delimiter 
如果你在切割後想要保留 separator, 可以使用 '(' 與 ')' 將 separator 中要保留的部分括起來. 下面代碼會保留 separator 的第一個數字: 
  1. #!/usr/bin/perl  
  2. use strict;  
  3. use warnings;  
  4.   
  5. my $data = 'Home1Work22Cafe333Work4444Home';  
  6. # \d+ matches one or more integer numbers  
  7. # The parenthesis () mean we keep the digits we match  
  8. my @values = split(/(\d)+/, $data);  
  9.   
  10. foreach my $val (@values)   
  11. {  
  12.     print "$val\n";  
  13. }  
  14. exit 0;  
執行結果: 
Home
1
Work
2
Cafe
3
Work
4
Home

- Example 10. Splitting into a hash 
如果已知道你的輸入字串是平衡的, 你可以直接將輸出轉成 hash. 參考範例如下: 
  1. #!/usr/bin/perl  
  2. use strict;  
  3. use warnings;  
  4.   
  5. my $data = 'FIRSTFIELD=1;SECONDFIELD=2;THIRDFIELD=3';  
  6. my %values =  split(/[=;]/, $data);  
  7.   
  8. foreach my $k (keys %values)   
  9. {  
  10.     print "$k: $values{$k}\n";  
  11. }  
  12. exit 0;  
執行結果為: 
FIRSTFIELD: 1
THIRDFIELD: 3
SECONDFIELD: 2


補充說明 : 
perldoc.perl.org - split 
Using the Perl split() function

[ Python 常見問題 ] How to shift a datetime object by 12 hours in python

Source From   Here   Question   Datetime   objects hurt my head for some reason. I am writing to figure out   how to shift a date time obje...