シェルを使用して特定のパターンを繰り返す

シェルを使用して特定のパターンを繰り返す

処理し、いくつかのアイテムをインポートする必要があるファイルがあります。ファイル形式は次のとおりです。

入力例:

String1:"Hello"
String2:"World"
String3:"Question"
End
String1:"HelloAgain"
String5:"Answer"
End
String1:"NewEntry"
String2:"Foo"
String5:"NewFile"
End

スクリプトは繰り返しString1を見つけて印刷しようとします。 String2もブロック内にある場合は、String1に追加されて印刷されます。

出力例:

Hello World
HelloAgain
NewEntry Foo

これらの各ブロックを繰り返す必要があります。ここでブロックは、各「End」文字列間の内容を意味します。次のスクリプトがあります。

    cat $1 | while read line
do
    if [[ $line == "String1="* ]];
    then
        string1=$line
    fi
    if [[ $line == "String2="* ]];
    then
        string2=$line
    fi
    if [[ $line == "End" ]];
    then
        if [ $string1 ];
            then
            echo "string1/"$string1"
        fi
        if [ $string1 ] && [ $string2 ];
            then
            echo $string1" "$string2
        fi
    #Reset values
    string1=''
    string2=''
    fi
done

コードはうまく機能しますが、これらのブロック間の処理がより複雑になる可能性があります。これらのブロックを繰り返してこれらのブロックエントリを処理する最良の方法は何ですか?

注:このファイルはプロパティファイルです。

答え1

あなたが提供した入力と要求された出力を考慮すると、次のようになります。

$ awk -F: '$0 == "End" { printf "\n" } $1 ~ /^String[12]$/ { gsub( /\"/, "", $2 ); printf( "%s ", $2)}' input
Hello World
HelloAgain
NewEntry Foo

答え2

perl -F':|"' -lane 'if ($out && $_ eq "End") {print "$out"; $out=""};
  $out  = $F[2] if ($F[0] eq "String1");
  $out .= $F[2] if ($out && $F[0] eq "String2")' input.txt

このPerlスクリプトは、出力から二重引用符を削除する必要がないように、フィールド区切り文字としてまたはを:使用します。"これは、我々が抽出する必要があることを意味します。第三フィールドの代わりに2番目のフィールドを使用します。最初のフィールド:".Perl配列は0から始まるので$F[2]

印刷する内容がある場合は、レコード(「チャンク」)の出力(String1自体)のみを印刷します。またはString1とString2が存在します。つまり、一致しないレコードに対して空行を印刷しません。

これは同じアルゴリズムですawk

awk -F':|"' 'out && $0 == "End"  { print out; out="" };
  $1 == "String1" { out=$3 };
  out && $1 == "String2" { out = out$3 }' input.txt

関連情報