- ベストアンサー
正規表現の 「 * 」
正規表現の 「 * 」は、直前パターンの繰り返しですよね? つまり、a* は a, aa, aaa, aaaa, aaaaa, ..... にマッチするわけですよね? ところで、 echo abbbaaa | sed 's/a*/x/g' のようにしたら a, aaa の部分が x に置き換わって → xbbbx となることを期待していたのですが、 → xbxbxbx となってしまいました。 なぜでしょうか?
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
「0個以上の繰り返し」は、通常以下のような場合に使います。 sed 's/#a*#/x/g' 入力文字 → 実行結果 (1) ## → x (2) #a# → x (3) #aa# → x (4) #ab# → #ab#(一致しないので変更無し) ポイント(「1個以上の繰り返し」との違いは)(1)で、「a」の存在が必須ではなく、 その前後の文字列との関係がキーになるような場合に便利なのです。(「1個以上の 繰り返し」だと、(1)は一致しません。) 実際にもっと有用な例を示します。 行末に「#」で始まるコメントが記述されているテキストの、コメント部分だけを削除 するには、以下のようにします。(以下、半角空白1文字を「△」で表現します。) sed 's/△*#.*$//g' 「△*」は、コメントまでの間に空白があった場合に、その空白も不要なので削除する為 に用います。これを「1個以上の繰り返し」にしてしまうと、コメントまでの間に空白 を含まないステートメントは、コメントが削除できずに残ってしまいます。 例) if(xxxx)△△△#xxxの判定 → if(xxxx) if(xxxx)#xxxの判定 → if(xxxx) 「#.*$」は、「#」の後の文字を行末まで全て削除します。「.」(任意の文字)の 「1個以上の繰り返し」にすると、「#」の後ろに文字が無いステートメントは削除でき ずに残ってしまいます。 例) if(xxxx)△#xxxの判定 → if(xxxx) if(xxxx)△# → if(xxxx) このように、「*」(0個以上の繰り返し)は本来、他のものと複合して使うことで効果 を発揮します。 ご質問の例のような条件の場合は、「1個以上の繰り返し」を使って下さい。 正規表現は、実際に複雑なパターンをいろいろ試して行くと、その利便性や真髄が解って きます。 プログラミング言語と同様に、「習うより慣れる」類のものかも知れません。
その他の回答 (3)
- επιστημη(@episteme)
- ベストアンサー率46% (546/1184)
> aとbの間も何もないので abbb の部分は → xxbxbxb となるべきだと思うのですがどうでしょうか? なるべく長い列をマッチさせようと試みるからです。
- επιστημη(@episteme)
- ベストアンサー率46% (546/1184)
> 正規表現の 「 * 」は、直前パターンの繰り返しですよね? 直前パターンの '0個以上の' 繰り返しです
- -izayoi-
- ベストアンサー率45% (48/105)
「*」は直前パターンの0個以上の繰り返しを表すので、このような結果になったと思います。 ご希望の結果を得るには、「a」の1個以上の繰り返しを指定します。 sedの正規表現に「+」があれば「a+」を、無い場合は「aa*」と指定してみて下さい。
補足
ありがとうございます。 「ゼロ個」の繰り返し、というのがピンとこないのですが、「何もない文字列」ということでしょうか? bとbの間は何もないので bbb の部分が → bxbxb となるのは分かります。 しかし、aとbの間も何もないので abbb の部分は → xxbxbxb となるべきだと思うのですがどうでしょうか? つまり、 a → x aとbの間 → x b → b bとbの間 → x b → b bとbの間 → x b → b ということですが。