LoginSignup
247
209

More than 5 years have passed since last update.

環境に依存しないワンライナーを書くならsedよりperlの方がいい

Last updated at Posted at 2015-02-22

まえがき


sedBSDGNUperlperl調

GNU sedBSD sedperlsed

sedGNU sedBSD sed


sed
$ echo 'hoge' | sed -E 's/(.*)g/\1/'



sedBSDGNU-EBSD sed使GNU sed使-r使

使使BSD sedGNU sedsedbasic regular expression(BRE)BREBREenhanced BREBSD sedBREGNUenhanced BRE1enhanced BRE\+, \?, \|使BRE使2 \+BRE\{1,\}, \?\{0,1\}\|BREBREobsolete3

BSD
$PATH:
GNU sed
$ echo $PATH | sed 's/:/\n/g'
/usr/local/bin
/usr/bin
/bin
/usr/local/games
/usr/games

こう書けるのに、BSD sedだと:nに変換される。

$ echo $PATH | sed 's/:/\n/g'
/usr/local/binn/usr/binn/binn/usr/local/gamesn/usr/games

同様のことをするにはこうする必要がある4

$ echo $PATH | sed 's/:/\'$'\n/g'
/usr/local/bin
/usr/bin
/bin
/usr/local/games
/usr/games

改行のところ呪文にしか見えない。
あるいは、バックスラッシュに続けて改行を入れる。

$ echo $PATH | sed 's/:/\
/g'
/usr/local/bin
/usr/bin
/bin
/usr/local/games
/usr/games


sed5

perl


perlsedBSDGNUperl56

sedperl



調sed

sed
$ echo -e "hoge\nfuga\npiyo" | sed -e 's/p/P/g; s/\(.*g\).*/\1/g;'
hog
fug
Piyo

perlでこう書く

$ echo -e "hoge\nfuga\npiyo" | perl -pe 's/p/P/g; s/(.*g).*/$1/g;'
hog
fug
Piyo




sedperl

-p

BREperl\(\)()

\1$1


sed

sedBSDGNUperlperl

sed使使

perl


sedperlsed

-eperl
-pperlsed
perl -pe 's/o/O/g'
while (<>) {
    s/o/O/g
} continue {
    print or die "-p destination: $!\n";
}

<>perl11
perl$_

while (defined($_ = <>)) {
    $_ =~ s/o/O/g
} continue {
    print $_ or die "-p destination: $!\n";
}

or1$_s/o/O/g$_$_print
perl -pe 's/o/O/g'sed -e 's/o/O/g'

perlwhile-e1-e



-p


-pawkBEGIN, END使
$ echo -e "hoge\nfuga\npiyo" | perl -pe 'BEGIN{$count=0} s/o/O/g; $count++; END{print $count, "\n"}'
hOge
fuga
piyO
3

awk同様変数は数値として扱う場合0で初期化されるので、この例の場合BEGINは省略できる。

$ echo -e "hoge\nfuga\npiyo" | perl -pe 's/o/O/g; $count++; END{print $count, "\n"}'
hOge
fuga
piyO
3

また、-lオプションをつけるとprintした時に勝手に改行を入れてくれる。

$ echo -e "hoge\nfuga\npiyo" | perl -ple 's/o/O/g; $count++; END{print $count}'
hOge
fuga
piyO
3

-nオプションで必要な行だけ出力 or 出力しない

必要なところだけ出力したい or そもそも出力したくない、という場合には-pではなく-nを使う。-nを使うと、以下のコードのように実行される。

while (<>) {
...             # your program goes here
}

-pオプションの時と比べてcontinueブロックがなくなっただけ。代わりに出力したいときは自前でprintする必要がある。例えば、先頭がfで始まる行のみ出力、とかだとこうする。

$ echo -e "hoge\nfuga\npiyo" | perl -ne 'print if /^f/;'
fuga

-pオプション同様、BEGIN, ENDが使えるので、例えば行数だけ数えて表示したい場合はこうなる

$ echo -e "hoge\nfuga\npiyo" | perl -nle '$count++; END{print $count}'
3

-aでawkっぽい処理


-aawkawk$1nperl-a@Fawk$1perl$F[0]awk$0perl$_

awk
$ echo "a1 b1 c1\na2 b2 c2" | awk '{print $2}'
b1
b2

perlではこうなる

$ echo "a1 b1 c1\na2 b2 c2" | perl -alne '{print $F[1]}'
b1
b2

これは具体的にはこういう処理が内部で走ってると思えばいい

while (<>) {
    @F = split(' ');
    ...             # your program goes here
}

また、awk同様-Fでセパレータを変更できる。セパレータは正規表現で指定も出来る。

$ echo "a1, b1, c1\na2, b2, c2" | perl -F'[0-9]' -alne '{print $F[1]}'
, b
, b

現在の行番号

$.が行番号になる。

$ echo "a\nb\nc\nd\ne\nf" | perl -nle 'print "$.:$_"'
1:a
2:b
3:c
4:d
5:e
6:f

空行区切り

-00オプションで空行区切り(paragraph mode)になる。

$ echo 'hoge\nfuga\n\npiyo\n\nbar\nbaz' | perl -00 -nle 'print if /^fuga$/m'
hoge
fuga

まとめ


sedperlsedperl
perl-psed7perl
perl使調sed
perl

参考



  1.  



    \s使BSDman 7 re_formatENHANCED FEATURES 



    man 7 re_formatobsolete使 



    http://nlfiedler.github.io/2010/12/05/newlines-in-sed-on-mac.html  



    BSD sedGNU sed 



    2015perl610perl6 



     
247
209
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
247
209