basefile.txt
多くの行の名前の付いたファイルがあります。ファイルのレコードは、コレクションに基づいて論理的にグループ化されます。
たとえば、
"GRP_START","LINE1"........
"A"
"B--BOOM"
"C"
"GRP_START","LINE1"........
"A"
"B--DOOM"
"C"
"D"
"E"
"F"
"G"
"GRP_START","LINE1"........
"E"
"F"
"G"
"C--MOOM"
"GRP_START","LINE1"........
私が望むのは、これらの検索文字列を次keywords.txt
のデータを含む別々のファイルに入れることです。
BOOM
DOOM
MOOM
ファイルからテキストを1つずつ読み、keywords.txt
そのテキストを検索してbasefile.txt
特定のレコードを書き込むコマンドが必要です。finalfile.txt
具体的な記録は次のとおりです。テキスト付きのコレクションを検索する必要があります。
例:上記のファイルから。
このコマンドはBOOMを検索し、次の行を返す必要があります。
"GRP_START","LINE1"........
"A"
"B--BOOM"
"C"
このコマンドはDOOMを検索し、次の行を返す必要があります。
"GRP_START","LINE1"........
"A"
"B--DOOM"
"C"
"D"
"E"
"F"
"G"
したがって、GRP_STARTはグループの開始から次のGRP_STARTまでの記録を記録したいと思いますfinalfile.txt
。
答え1
次のawk
スクリプトはデータファイルを読み取り、各レコードをlines
変数に一時的に保存します。word
変数のキーワードがレコードに見つかると、do_output
変数は1(true)に設定されます。キーワードが見つかり、次のレコードまたはファイルの終わりに達すると、キーワードレコードが出力されます。
#!/usr/bin/awk -f
/^"GRP_START"/ {
if (do_output) {
exit;
}
lines = $0;
next;
}
$0 ~ word {
do_output = 1;
}
{
lines = sprintf("%s\n%s", lines, $0);
}
END {
if (do_output) {
print lines;
}
}
テストしてみてください:
$ awk -v word="MOOM" -f script.awk basefile.txt
"GRP_START","LINE1"........
"E"
"F"
"G"
"C--MOOM"
その後、必須キーワードを繰り返すだけです。
#!/bin/sh
while read -r word; do
awk -v word="$word" -f script.awk basefile.txt
done <keywords.txt >finalfile.txt
今後の改善のための提案:まずキーワードを配列に読み込み、basefile.txt
データファイルを一度だけ解析します。
答え2
努力する:
awk 'FNR==NR{re=re (re?"|":"")$0;next} /^"GRP_START"/{if (rec~re)print rec; rec=$0;next} {rec=rec"\n"$0} END{if (rec~re)print rec}' keywords.txt basefile.txt
例:
$ awk 'FNR==NR{re=re (re?"|":"")$0;next} /^"GRP_START"/{if (rec~re)print rec; rec=$0;next} {rec=rec"\n"$0} END{if (rec~re)print rec}' keywords.txt basefile.txt
"GRP_START","LINE1"........
"A"
"B--BOOM"
"C"
"GRP_START","LINE1"........
"A"
"B--DOOM"
"C"
"D"
"E"
"F"
"G"
"GRP_START","LINE1"........
"E"
"F"
"G"
"C--MOOM"
どのように動作しますか?
FNR==NR{re=re (re?"|":"")$0;next}
最初のファイルの読み込み中に
keywords.txt
すべての単語に一致する正規表現を設定します。たとえば、サンプルデータの場合、re
値はBOOM|DOOM|MOOM
。/^"GRP_START"/{if (rec~re)print rec; rec=$0;next}
新しいレコードの先頭に達するたびに、最後に保存されたレコードがに保存されている正規表現と
rec
一致することを確認してくださいre
。それでは印刷してみましょう。次に、rec
現在の行にリセットするには、残りのコマンドをスキップしてそのnext
行に移動します。rec=rec"\n"$0
他のすべての行の場合はこれをに追加します
rec
。END{if (rec~re)print rec}
ファイルを読み取ったら、最終レコードが正規表現と一致することを確認し、一致した場合に
re
印刷します。