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

단어 집합 중 적어도 하나를 포함하는 파일 집합에서 모든 줄을 가져오려는 것 같습니다.

당신이하지 않는다고 가정수천파일에서 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파일당 한 번씩 명령이 실행됩니다.

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가 이 작업을 더 효율적으로 수행할 수 있습니다.)

관련 정보