- ベストアンサー
sedで正規表現の後方参照を使いたい。
後方参照の練習をしようとしています。 1111:2222:3333:4444 5555:6666:7777:8888 というファイルを:でフィールドを区切って1列目と2列目を sedをつかってひっくり返そうとしました。 sed 's/^(\d{4}):(\d{4})/^$2:$1/' test.file などいろいろやってみたのですがうまくいきません。 良ければ教えてください。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
伝統的には、grep コマンドでつかうのが「正規表現」、egrep コマンドで使うのが「拡張正規表現」で、Perl等のは拡張正規表現のさらに拡張になってます。 すでに出ているように、( | ) { } 等が文字そのままの意味なのか正規表現の特殊文字なのかの切り替えに \ をつけるかつけないかなどが違います。 ここにまとめられています。 http://www.kt.rim.or.jp/~kbk/regex/regex.html
その他の回答 (3)
- sakusaker7
- ベストアンサー率62% (800/1280)
> これは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自体にしても バージョンによって拡張されている範囲に違いがあったり、 独自の拡張が加えられていたりするので使うときには注意が必要です。
お礼
ありがとうございます。 詳しくありがとうございました。 よく分かりました。^^
- sakusaker7
- ベストアンサー率62% (800/1280)
> 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フラグもいらないんじゃ?
お礼
ありがとうございます。 得たい結果を得ることができました。 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の正規表現の表記が特殊ということでしょうか?
- sakusaker7
- ベストアンサー率62% (800/1280)
Perlの正規表現を使って書いちゃってますね。 GNU sedの新しいのだとオプション指定でPerl表記の正規表現を 受け付けるようにできますが、ふつーのsedはそんなことはできません。 \d は使えません → [0-9] を使用 後方参照で使うためのカッコは ( ) ではなく \( \) です 回数指定のブレースは、\を前置します。 置換文字列の中で後方参照をするときに使うのは $ ではなく \ です。 あえて答えそのものは書きませんので試してみてください。
お礼
ありがとうございます。 Perlだけで使える文法だったんですね。 bash-3.2$ sed 's/^\([0-9]+\):\([0-9]+\)/^\2:\1/g' test 1111:2222:3333:4444 5555:6666:7777:8888 とやってみたのですが、まだうまくいきません。 難しいですね。><
お礼
ありがとうございます。正規表現にもいろいろあるのですね。^^