最近更新: 2008-03-06

Regex~~look-ahead assertion

有一字串,其格式為以逗號 (,) 分隔的記錄,例如 "a","b","c"。當某些欄位之值為空白時,會有逗號相連的情形,例如 "a",,"c"

現在要用字樣規則式(Regular Expression, Regex)修改空白欄位的表達方式,改成一個空字串 (""),一般我們會寫成 s/,,/,"",/g (by Perl)。不過這種寫法碰到連續多個空白欄位時,例如 "a",,,"c",會變成 "a","",,"c",得不到我們要的結果。因為 Regex 解析器在找到第一組 ,, 後,會把處理指標放在第3個逗號的位置上。當 Regex 解析器進行下一個比對動作時,它將從第3個逗號開始尋找,此時它看到的只有一個逗號,故判定不符合樣式,也就不會進行替換動作。

碰到這種情形,我們要用 look-ahead assertion (前瞻斷言) 處理。 Look-ahead assertion 的語法為 (?=pattern)。See also perlre::Look-Around Assertions

前瞻斷言 (look-ahead assertion) 的意義為: 我的樣式要接著一個前瞻斷言樣式,但不包含那個前瞻斷言樣式。因為它的意義是"不包含",所以,Regex 解析器不會把處理指標放在前瞻斷言樣式之後。

例如: a,,,b,,c

字串:a,,,b,,c
指標:01234567

若以 s/,,/,"",/g 進行替換。當 Regex 找到第一組逗號時,它會把處理指標放在 3 的位置。下一個比對動作將從指標 3 的位置開始找。這就得不到我們要的結果。

若要改成我們要的結果,則以前瞻斷言改寫成 s/,(?=,)/,""/g (注意替換字串是 ,"")。 這時的意義是: 尋找有一個逗號且接著另一個逗號的樣式,但不包含另一個逗號。因為我們說"不包含"另一個逗號,所以 Regex 找到第一組逗號時,它將會把指標放在 2 的位置。下一個比對動作將從指標 2 的位置開始找。如此就能得到我們要的結果。

Perl
$s = 'a,,,b,,c';
$s =~ s/,(?=,)/,""/g;
print "$s\n";
PHP
<?php
$s = "a,,,b,,c";
echo preg_replace('/,(?=,)/', ',""', $s);
?>
JavaScript
s = 'a,,,b,,c';
print( s.replace(/,(?=,)/g, ',""') );

See also: Regular Expression (RegExp) in JavaScript

Ruby
s = 'a,,,b,,c'
print s.gsub(/,(?=,)/ , ',""')
樂多舊網址: http://blog.roodo.com/rocksaying/archives/5645437.html