• ベストアンサー
  • 暇なときにでも

sedで正規表現の後方参照を使いたい。

  • 質問No.2919423
  • 閲覧数3720
  • ありがとう数5
  • 気になる数0
  • 回答数4
  • コメント数0

お礼率 50% (78/153)

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

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

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

質問者が選んだベストアンサー

  • 回答No.3
  • ベストアンサー

ベストアンサー率 48% (4483/9307)

伝統的には、grep コマンドでつかうのが「正規表現」、egrep コマンドで使うのが「拡張正規表現」で、Perl等のは拡張正規表現のさらに拡張になってます。
すでに出ているように、( | ) { } 等が文字そのままの意味なのか正規表現の特殊文字なのかの切り替えに \ をつけるかつけないかなどが違います。

ここにまとめられています。
http://www.kt.rim.or.jp/~kbk/regex/regex.html
お礼コメント
vivi0303

お礼率 50% (78/153)

ありがとうございます。正規表現にもいろいろあるのですね。^^
投稿日時:2007/04/14 14:35

その他の回答 (全3件)

  • 回答No.4

ベストアンサー率 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自体にしても
バージョンによって拡張されている範囲に違いがあったり、
独自の拡張が加えられていたりするので使うときには注意が必要です。
お礼コメント
vivi0303

お礼率 50% (78/153)

ありがとうございます。
詳しくありがとうございました。
よく分かりました。^^
投稿日時:2007/04/14 14:35
  • 回答No.2

ベストアンサー率 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フラグもいらないんじゃ?
お礼コメント
vivi0303

お礼率 50% (78/153)

ありがとうございます。
得たい結果を得ることができました。
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
  • 回答No.1

ベストアンサー率 62% (800/1280)

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

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

あえて答えそのものは書きませんので試してみてください。
お礼コメント
vivi0303

お礼率 50% (78/153)

ありがとうございます。
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にはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。
関連するQ&A

その他の関連するQ&Aをキーワードで探す

ピックアップ

ページ先頭へ