| perl -0777 -pe 's/xxx/yyy/g'

| No Comments | No TrackBacks

這是一條常用的單行程式,其作用是:讀取 STDIN,把其中 xxx 出現的地方全部都換成 yyy,然後印出來。

其中的 -0777 這個參數很有意思,它表示:讀 STDIN 時一次全部讀完。這是一個短線字符,後面跟著四個數字:零、七、七、七(而不是英文字母的 O。)

Perl 語言有個讀取 IO handle 用的運算符寫成 <>,叫做「鑽石運算符」。預設會一次讀取一行資料進來:

my $line_1 = <>; # 第一行
my $line_2 = <>; # 第二行
my $line_3 = <>; # 第三行

不過如果改了 $/ 變數的值,就可以改變每次讀取的單位。此變數預設的值是 \n,既換行字符。<> 的行為基本上是「從目前的位置開始讀,一直讀到把下個 $/ 讀進來為止」這樣的感覺。也就是說,如果有段資料 (假設存在 test.txt)是這樣:

My uncle was the town drunk -- and we lived in Chicago.
            -- George Gobel

我們可以把 $/ 改成 “—” 試試(假設這段程式存在 test.pl):

use 5.010;

$/ = "--";

my $line_1 = <>;
my $line_2 = <>;
my $line_3 = <>;

say "[$line_1]";
say "[$line_2]";
say "[$line_3]";

執行 cat test.txt | perl test.pl 會得到:

[   My uncle was the town drunk --]
[ and we lived in Chicago.
[ George Gobel

可知資料依 "--" 的出現而分成三段了。

如果做了 $/ = undef 的話,則是讓 <> 一次吃進所有資料。而命令列參數上的 -0777 就有等同於 $/ = undef 的效果。

這部份的原因,引述自 perlrun 這份文件 (perldoc perlrun):


specifies the input record separator ($/ ) as an octal or hexadecimal number. If there are no digits, the null character is the separator. Other switches may precede or follow the digits. For example, if you have a version of find which can print filenames terminated by the null character, you can say this:

find . -name '*.orig' -print0 | perl -n0e unlink

The special value 00 will cause Perl to slurp files in paragraph mode. The value 0777 will cause Perl to slurp files whole because there is no legal byte with that value.

If you want to specify any Unicode character, use the hexadecimal format: -0xHHH…, where the H are valid hexadecimal digits. (This means that you cannot use the -x with a directory name that consists of hexadecimal digits.)

No TrackBacks

TrackBack URL: http://pub.gugod.org/mt/mt-tb.cgi/251

Leave a comment