"test_result.txt"ファイルに特定の行を追加するために大量のファイルを処理しようとしています。次のコードを使用して達成しました。それほどエレガントではありません。
for i in *merged; do
while read -r lo; do
if [[ $lo == *"ID"* ]]; then
echo $lo >> test_result.txt
fi
if [[ $lo == *"Instance"* ]]; then
echo $lo >> test_result.txt
fi
if [[ $lo == *"NOT"* ]]; then
echo $lo >> test_result.txt
fi
if [[ $lo == *"AI"* ]]; then
echo $lo >> test_result.txt
fi
if [[ $lo == *"Sitting"* ]]; then
echo $lo >> test_result.txt
done < $i
done
しかし、サイズを小さくするために配列を試してみましたが、やや失敗しました。
KEYWORDS=("ID" "Instance" "NOT" "AI" "Sitting" )
KEY_COUNT=0
for i in *merged; do
while read -r lo; do
if [[$lo == ${KEYWORDS[@]} ]]; then
echo $lo >> ~/Desktop/test_result.txt && KEY_COUNT="`expr $KEY_COUNT + 1`"
fi
done < $i
done
答え1
単語セットの少なくとも1つを含むファイルセットからすべての行を取得したいようです。
あなたがしないと仮定数千ファイル内のgrep
単一のコマンドでこれを行うことができます。
grep -wE '(ID|Instance|NOT|AI|Sitting)' ./*merged >outputfile
これにより、パターンにリストされている単語と一致する名前が一致するファイルから行が抽出されます*merged
。
withは、指定された-w
文字列がgrep
部分文字列と一致しないことを確認します(つまり、NOT
内で一致しないNOTICE
)。このオプションを使用すると、-E
パターンを変更できます。|
-h
一致する行のファイル名を出力に含めない場合は、このオプションをコマンドに追加します。
何千ものファイルがあると、コマンドラインが長すぎて上記のコマンドが失敗する可能性があります。この場合、次のことができます。
for file in ./*merged; do
grep -wE '(ID|Instance|NOT|AI|Sitting)' "$file"
done >outputfile
grep
ファイルごとに1回ずつコマンドが実行されます。
find . -maxdepth 1 -type f -name '*merged' \
-exec grep -wE '(ID|Instance|NOT|AI|Sitting)' {} + >outputfile
grep
これにより、一度にできるだけ多くのファイルを呼び出すことができる回数が減ります。
関連:
答え2
配列を追加することは特に役に立ちません。それでも配列の要素を繰り返す必要があります(参照:項目がbash配列にあるかどうかをテストする方法は?):
while read -r lo; do
for keyword in "${keywords[@]}"; do
if [[ $lo == *$keyword* ]]; then
echo $lo >> ~/Desktop/test_result.txt && KEY_COUNT="`expr $KEY_COUNT + 1`"
fi
done
done < "$i"
次の文を使用する方が良いかもしれませんcase
。
while read -r lo; do
case $lo in
*(ID|Instance|NOT|AI|Sitting)*)
echo "$lo" >> ~/Desktop/test_result.txt && KEY_COUNT="`expr $KEY_COUNT + 1`"
;;
esac
done < "$i"
(ループがこの行をさらに処理すると仮定します。そうしないと、grepまたはawkがこれをより効率的に実行できます。)