dポイントプレゼントキャンペーン実施中!

後方参照の練習をしようとしています。
1111:2222:3333:4444
5555:6666:7777:8888

というファイルを:でフィールドを区切って1列目と2列目を
sedをつかってひっくり返そうとしました。

sed 's/^(\d{4}):(\d{4})/^$2:$1/' test.file
などいろいろやってみたのですがうまくいきません。
良ければ教えてください。

A 回答 (4件)

伝統的には、grep コマンドでつかうのが「正規表現」、egrep コマンドで使うのが「拡張正規表現」で、Perl等のは拡張正規表現のさらに拡張になってます。


すでに出ているように、( | ) { } 等が文字そのままの意味なのか正規表現の特殊文字なのかの切り替えに \ をつけるかつけないかなどが違います。

ここにまとめられています。
http://www.kt.rim.or.jp/~kbk/regex/regex.html
    • good
    • 2
この回答へのお礼

ありがとうございます。正規表現にもいろいろあるのですね。^^

お礼日時:2007/04/14 14:35

> これはsedで正規表現を使う場合、記号はエスケープする必要が


> あるということでしょうか?
> またsedで使える正規表現とperlで使える正規表現がちがうと
> 思うのですがperlの正規表現の表記が特殊ということでしょうか?

まずはじめに。
#3の方の回答にあるとおり、大きく分けると grep/sed で使われていたもの、
egrep/awk で使われていたもの、perlで使われているもの。の三つになります。

おおまかに古いほうから grep → sed → egrep → awk → perl の順です。
'*'とか'^','$'
などを見てもわかるとおり、grep/sedの正規表現でも記号類すべてに'\'を
つけなければメタ文字にならないということはありません。
'('とか'{'に'\'が要求されるのは、おそらくCのソースなんかを検索するときに
'\'がついていない'('はメタ文字にならないほうが都合がよいからでしょう。
#という話を昔聞いたことがあります
その割に '['は違ったりするのですけどね。

egrepは、grep/sedで用いられていたのとは違ったアルゴリズムで正規表現検索を
実現していました。そのため新たな別プログラムになっていたりするのですが、
なぜ '(', '{' の扱いが変わったのかはわかりません。
#Aho博士に訊いてください

んでPerl。
POSIXという規格では、grep/sedの受け付ける正規表現を「基本正規表現(Basic Regular Expression)」、
egrep/awkの受け付けるものを「拡張正規表現(Extended Reguar Expression)」
のように分類していますが、実は拡張正規表現は基本正規表現のすべてを含んだものではありません。
斯様にごちゃごちゃしたものがありましたので、Perl3か4の時点でPerlの
original autherであるLarry Wallが

・使える正規表現は基本正規表現+拡張正規表現とし
・記号がメタ文字になる場合はそれのみでなるようにし、基本正規表現にあるような'\(' や '\{' という表記は採用しない

といった規則のもとでまとめました。
そしてPerl 5でいわゆるPerl拡張が導入されました。

Perl互換の正規表現というと、このPerl 5での拡張をサポートしているかどうか
で言われますが、実は言語とかライブラリによってとかPerl自体にしても
バージョンによって拡張されている範囲に違いがあったり、
独自の拡張が加えられていたりするので使うときには注意が必要です。
    • good
    • 0
この回答へのお礼

ありがとうございます。
詳しくありがとうございました。
よく分かりました。^^

お礼日時:2007/04/14 14:35

> bash-3.2$ sed 's/^\([0-9]+\):\([0-9]+\)/^\2:\1/g' test


> 1111:2222:3333:4444
> 5555:6666:7777:8888
>
> とやってみたのですが、まだうまくいきません。

あー(笑)
sed は + も使えません。
ただし、GNU sed だったら \+ と書くことでPerlの+と
同じ意味にすることができます。

あと、置換パターンの先頭にある ^ は何のために?
もうひとつgフラグもいらないんじゃ?
    • good
    • 0
この回答へのお礼

ありがとうございます。
得たい結果を得ることができました。
bash-3.2$ sed 's/^\([0-9]\{4\}\):\([0-9]\{4\}\)/\2:\1/' test
2222:1111:3333:4444
6666:5555:7777:8888

これはsedで正規表現を使う場合、記号はエスケープする必要が
あるということでしょうか?
またsedで使える正規表現とperlで使える正規表現がちがうと
思うのですがperlの正規表現の表記が特殊ということでしょうか?

お礼日時:2007/04/14 07:31

Perlの正規表現を使って書いちゃってますね。


GNU sedの新しいのだとオプション指定でPerl表記の正規表現を
受け付けるようにできますが、ふつーのsedはそんなことはできません。

\d は使えません → [0-9] を使用
後方参照で使うためのカッコは ( ) ではなく \( \) です
回数指定のブレースは、\を前置します。
置換文字列の中で後方参照をするときに使うのは $ ではなく \ です。

あえて答えそのものは書きませんので試してみてください。
    • good
    • 0
この回答へのお礼

ありがとうございます。
Perlだけで使える文法だったんですね。

bash-3.2$ sed 's/^\([0-9]+\):\([0-9]+\)/^\2:\1/g' test
1111:2222:3333:4444
5555:6666:7777:8888

とやってみたのですが、まだうまくいきません。
難しいですね。><

お礼日時:2007/04/14 03:58

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!