
処理し、いくつかのアイテムをインポートする必要があるファイルがあります。ファイル形式は次のとおりです。
入力例:
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