Bash - 入れ子になった[FOR、WHILE、IF]ステートメントの配列を繰り返し

Bash - 入れ子になった[FOR、WHILE、IF]ステートメントの配列を繰り返し

"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がこれをより効率的に実行できます。)

関連情報