awkを使う

awkを使う

以下にサンプルテキストファイル(test_long_sentence.txt)があり、不要なデータを除いてtest1を含むすべての行をgrepしたいと思います。

見積もりが完了する前にどのようにデータを収集できますか?

test_long_sentence.txt

This is some unwanted data blah blah blah

20  /test1/catergory="Food"
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"
20  /test1/type="Western"

This is some unwanted data blah blah blah

20  /test1/theme="Halloween"

注文する:

grep "test1" test_long_sentence.txt

実際の出力:

20  /test1/catergory="food"
20  /test1/target="Adults, \"Goblins\", Elderly,
20  /test1/type="Western"
20  /test1/theme="Halloween"

予想出力:

20  /test1/catergory="food"
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"
20  /test1/type="Western"
20  /test1/theme="Halloween"

PS:私はtest_long_sentence.txtの編集を制御できません。だから私に一行で編集するように頼まないでください。

ベストアンサー1

awkを使う

$ awk '/test1/{line=$0; while (!(line ~ /[^\\]".*[^\\]"/)) {getline; line=line "\n" $0}; print line}' sentence.txt 
20  /test1/catergory="Food"
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"
20  /test1/type="Western"
20  /test1/theme="Halloween"

/test1/条件です。現在の行に regex と一致する内容が含まれている場合、中かっこで囲まれたtest1コマンドが実行されます。これらのコマンドは次のとおりです。

  • line=$0

    現在の行の内容は「line」変数に格納されます。

  • while (!(line ~ !/[^\\]".*[^\\]"/)) {getline; line=line "\n" $0}

    現在のコンテンツにlineエスケープされていない2つの引用符が含まれていない場合は、次の行を取得してviagetlineに追加します。lineline=line "\n" $0

  • print line

    変数には、lineエスケープされていない2つの引用符が含まれており、それを印刷します。

コマンドを複数行にわたって分散したい場合は、上記と同じコマンドを次のように作成できます。

awk '
    /test1/{
        line=$0
        while (!(line ~ /[^\\]".*[^\\]"/)) {
            getline
            line=line "\n" $0
        }
        print line
    }' sentence.txt 

sedを使う

$ sed -n '/test1/{:a; /[^\\]".*[^\\]"/{p;b}; N; ba}' sentence.txt 
20  /test1/catergory="Food"
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"
20  /test1/type="Western"
20  /test1/theme="Halloween"

仕組み:

  • -n

    これは、明示的に要求されない限り、sedが何も印刷しないように指示します。

  • /test1/{...}

    埋め込み行に対して、test1次のように中括弧で囲まれたコマンドを実行します。

    • :a

      これはラベルを定義しますa

    • /[^\\]".*[^\\]"/{p;b}

      パターンスペースに現在エスケープされていない2つの引用符が含まれている場合は、パターンスペースを印刷して残りのpコマンドをスキップしてb次の行から始めます。

    • N

      ここに到達すると、現在エスケープされていない引用符が2つないことを意味します。パターン空間として次の行を読み込みます。

    • ba

      ラベルに戻り、aそのラベルの後にコマンドを繰り返します。

おすすめ記事