2013-01-31 68 views
0

在Perl中,我試圖從一段文本中構建所有單詞的數組。拆分所有單詞但保留拆分字符

現在我使用@tokens = split /[^\w']+/, $mytext;

這似乎是讓所有的alphanum話,但我希望所有的標點符號被認爲是一個字除外下劃線。實施例

hi. my name is first_last ...

應該變成的話:喜。 ,我的名字是,first_last,。 ,。 ,。

共9個單詞。

我該怎麼做?我嘗試在標點符號上分割,但沒有保存標點符號。

回答

0

一種方法是使用lookaround assertions:你想分割(1)空白; (2)前一個字符在[^\w'](除了字符串結束處); (3)只要下一個字符是在[^\w'](除了在啓動的字符串),所以你可以寫:

@tokens = split /\s+|(?<=[^\w'])|(?=(?!^)[^\w'])/, $mytext; 
2

往往更容易搭配不是分裂;這聽起來像你想匹配任何系列的單引號/字字符(包括_)或任何單一其他非空白字符:

my $mytext = 'hi. my name is first_last ...'; 
my @tokens = $mytext =~ /([\w']+|\S)/g; 
print join(' , ', @tokens),"\n"; 

生產:

hi , . , my , name , is , first_last , . , . , . 

[\w']是一個字符類允許任何單詞字符(字母,數字或下劃線)或單引號;可以添加其他字符,儘管有些字符可能需要被轉義(例如[\w'\-]添加連字符)。

+0

@TLP謝謝,修復 – ysth

+0

這是什麼部分允許_在單詞中?如果我想要一個字中允許另一個字符,就像連字符一樣? –

+0

@RiceNewman'_'在'\ w'字符類中。 – TLP

0
perldoc -f split 
==> 
    split /PATTERN/,EXPR,LIMIT 
    split /PATTERN/,EXPR 
    split /PATTERN/ 
    split Splits the string EXPR into a list of strings and returns that 
      list. By default, empty leading fields are preserved, and empty 
      trailing ones are deleted. (If all fields are empty, they are 
      considered to be trailing.) 
    ... 
      If the PATTERN contains parentheses, additional list elements 
      are created from each matching substring in the delimiter. 

       split(/([,-])/, "1-10,20", 3); 

      produces the list value 

       (1, '-', 10, ',', 20) 
    ... 

新增:

在代碼:

my $inp = 'hi. my name is first_last ...'; 
my @parts = split /(\W)/, $inp; 
printf "%d parts: (%s)\n", scalar @parts, join('), (', @parts); 
@parts = grep {$_ gt ' '} @parts; 
printf "%d parts: (%s)\n", scalar @parts, join('), (', @parts); 

輸出:

18 parts: (hi), (.),(), (), (my), (), (name), (), (is), (), (first_last), (),(), (.),(), (.),(), (.) 
9 parts: (hi), (.), (my), (name), (is), (first_last), (.), (.), (.) 
1

如果這些是你的話

hi. my name is first_last ... 
11 22 3333 44 5555555555 

而這些都不是你的分隔符

hi. my name is first_last ... 
    11 22 33 4   5555 

,那麼你實際上並沒有分裂的話(和split可能不會正常工作)。你實際上需要一個記號器。

這裏的建設tokeniser的通用方法:

my @tokens; 
for ($mytext) { 
    /\G \s+ /xgc; 
    if (/\G ([\w']+ ) /xgc) { push @tokens, $1; redo; } 
    if (/\G ([^\s\w']) /xgc) { push @tokens, $1; redo; } 
    die "Bad code"; 
} 

但我們可以簡化。

my @tokens = $mytext =~ /\G\s*([\w']+|[^\S\w'])/g; 

甚至

my @tokens = $mytext =~ /\G\s*([\w']+|\S)/g; 
0

擴展在YSTH的想法:

my $mytext = 'hi. My name22222 is first_last!? 2,0 #@/'; 
my @tokens = $mytext =~ /([a-zA-Z_]+|[0-9]+|[.?!,])/g; 
print join ":", @tokens,"\n"; 

輸出:

hi:.:My:name:22222:is:first_last:!:?:2:,:0: 

這很容易理解,因爲它避免W¯¯使用\和\ S。 \ w涵蓋的內容比你想象的要多,因爲它包含了令人困惑的內容。 \ S也不僅僅是標點符號。

以上顯示瞭如何使用|拆分可以組成一個單詞的字符集,並明確定義字符。不包含任何單詞的「垃圾」被過濾掉。