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

バッチファイルで、2個以上の文字列を順番問わずマッチさせたいと考えています。

例えば、
「111 222 333 444 555 666 777」
という内容のテキストファイルがあったとして、

sedコマンドを使って
「222」と「444」と「666」が
この順番で含まれている行を置換したい場合、

sed -e "s/.*222.*444.*666.*/置換後の文字列/" in.txt > out.txt

とすれば、問題なく置換されると思います。

しかし、上記の例では、
「777 666 555 444 333 222 111」
という内容のテキストファイルは置換されません。

文字列の順番を問わず、
「222」と「444」と「666」が含まれている行ならば、
その行を置換する、といった事は出来ないでしょうか。

sedコマンド以外でも構いませんので、何かいい方法をご存知の方がおられましたらお教え頂けないでしょうか。

A 回答 (3件)

awk '/222/&&/444/&&/666/{print "MATCHED";next}{print}'



正規表現で 222 444 666 が出てくる順番の6通りを網羅すればいいので、sedだけでも出来ます。

この回答への補足

ご回答ありがとうございます。

自分はプログラミング等の難しい事は解らず、簡単なコマンドを連続させて使う程度なのですが、正直、お教え頂いたawkも使い方がよく分からず、うまく動作させる事が出来ません。sedでも実現出来るとの事で、そちらの方向で行きたいと思います。

sedでも、
「222.*444.*666」「222.*666.*444」
「444.*222.*666」「444.*666.*222」
「666.*222.*444」「666.*444.*222」
と、書けばいいのかも知れませんが、

今回、このバッチファイルを使用したい理由が、商品のタイトルが数千書かれているリストから、「●●」「■■」「▲▲」という単語を含む行は削除する、といった用途でして、商品タイトル以外の情報も記載されている為、ファイルの容量が大きいのです。

つまり、sedを6回実行していると、それだけ時間も要すると思いますので、出来ればそれはしたくなかったのです。

それに、検索するキーワードも、どんどん追加していかないといけない為、その度にキーワードの並びを変えて、6個のパターンを作り、キーワードのリストに書き込んでいくという作業も、大変手間な訳です。

ですので、「●● ■■ ▲▲」と、キーワードのリストに一行書き込むだけでいいようにしたかったのです。

キーワードのリストは、後でまとめて、sedコマンドに当てはまるように置換して、バッチファイルとして実行しています。それは既に実現出来ています。

ですので、今考えている事としましては、「●● ■■ ▲▲」というキーワードが書かれていれば、そこから自動で6つのパターンを生成して、それをsedコマンドに当てはめて、実行するという処理を書こうかと考えています。

処理速度の問題も、なんとか考えて解決したいと思います。

ご回答、本当にありがとうございました。

補足日時:2013/07/21 22:50
    • good
    • 0
この回答へのお礼

色々なWEBページを参考にして、試行錯誤していたのですが、無事に目的の動作が出来ました。
ありがとうございました。

最初の補足を投稿させて頂く前に、検索エンジンで色々調べてやっていたのですが、結果として、その時にやっていたコマンドの基本的な構文は間違っていませんでした。

しかし、こちらの環境がWindows環境な為、「'」「"」の扱いが他のOSとは違っていて、その為にエラーになっていた様です。

お教え頂いたコマンドを、以下の様に書き換えさせて頂いて、実行してみると、うまく動作してくれました。

awk "/222/&&/444/&&/666/{print \"MATCHED\";next}{print}" in.txt > out.txt

お教え頂いたこの方法が、一番良いと思うので、この方法でやっていこうと思います。
大変助かりました。本当にありがとうございました。

お礼日時:2013/07/22 11:20

sedの命令は


アドレス(範囲) コマンド (必要なら)引数
となっています。
指定したアドレスだけに、コマンドを実行する、というものです。

s/AAA/BBB/
というのは
アドレス: 省略されている=全行が対象
コマンド: s
引数: /AAA/BBB/
ということです。

アドレスでは、行番号を指定したりできますが、「正規表現に一致した行」を対象とする、というものがあります。

命令同士は ; や改行で区切って複数記述できます。
また、{ コマンドという 、複数のコマンドをまとめるコマンドと、}コマンドという、{の終了を表わすコマンドがあります。

これらを組み合わせると
/条件1/{/条件2/{s/.*条件3.*/置換後/;};}
という方法があります。
これは
アドレス: /条件1/ → 条件1 という正規表現にマッチする行が対象
コマンド: { → 対応する } までを一つのコマンドとして扱う
引数: /条件2/{s/.*条件3.*/置換後/;} → これをコマンドとして実行する
; で上記コマンドの区切り
} コマンドで、上記 { の終了
となります。

この方法での欠点は、条件によっては意図した動作にならないことです。
条件1: 12
条件2: 23
条件3: 34
の様に重複した文字があると
1234
→ 12.*23.*34 等では対象外
→ /12/,/23/,/34/と分けると、すべてマッチするので対象
となってしまいます。

そこまで対応しようとしたら、sedではちょっと難しいかな、と思います。
awk,perl等が便利でしょう。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
大変丁寧に解説して頂きありがとうございます。

まだ今の自分では、ご説明頂いた全てを理解する事は出来ませんが、何度も読み返して理解して行こうと思います。

ご回答頂いた通りにテストしてみました。
うまく動作してくれました。
ありがとうございました。

ただ、逆に「条件によっては意図した動作にならない」というケースが、まだ今の自分では理解出来ていませんので、今度、時間を掛けて理解して行こうと思います。

何より、sedに対する知識が少し増えた事が嬉しいです。
違うケースでも活用して行こうと思います。
awkやperl等も今後は勉強して行こうと思います。

ご回答、本当にありがとうございました。

お礼日時:2013/07/22 10:37

No1です。


sedが使えるのに、あの程度の簡単なawkが使えないというのがよくわかりませんが、sedでやるなら、

#!/bin/sh
K1=222
K2=444
K3=666
X=置換後の文字列

sed -e "s/.*$K1.*$K2.*$K3.*/$X/" -e "s/.*$K1.*$K3.*$K2.*/$X/" -e "s/.*$K2.*$K3.*$K1.*/$X/" -e "s/.*$K2.*$K1.*$K3.*/$X/" -e "s/.*$K3.*$K1.*$K2.*/$X/" -e "s/.*$K3.*$K2.*$K1.*/$X/" in.txt >out.txt
    • good
    • 0
この回答へのお礼

再度、ご回答頂きありがとうございます。

awkはsedより簡単なのですね。awkも勉強して行こうと思います。

あと、当方の環境を書き忘れておりまして、こちらはWindows環境です。書き忘れていてすみませんでした。

ですので、お教え頂いたコマンドをWindows用に書き換えさせて頂いて、

set K1=222
set K2=444
set K3=666
set X=置換後の文字列

sed -e "s/.*%K1%.*%K2%.*%K3%.*/%X%/" -e "s/.*%K1%.*%K3%.*%K2%.*/%X%/" -e "s/.*%K2%.*%K3%.*%K1%.*/%X%/" -e "s/.*%K2%.*%K1%.*%K3%.*/%X%/" -e "s/.*%K3%.*%K1%.*%K2%.*/%X%/" -e "s/.*%K3%.*%K2%.*%K1%.*/%X%/" in.txt > out.txt

とやってみましたら、無事に成功しました。
ありがとうございました。

勉強不足でお恥ずかしいです。
もっとコマンドを勉強して行こうと思います。
お手数をお掛け致しました。

ご回答、本当にありがとうございました。

お礼日時:2013/07/22 11:05

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