스크립트에서 grep의 출력을 어떻게 안전하게 사용할 수 있습니까?

스크립트에서 grep의 출력을 어떻게 안전하게 사용할 수 있습니까?

스크립트에서 일부 텍스트가 포함된 파일을 찾고 싶습니다. 텍스트가 있는 파일과 텍스트가 있는 파일의 전체 줄을 알아야 합니다. grep이 작업을 수행하는 유틸리티이지만 가능한 경우 출력을 :파일 이름에서 사용 가능한 형식으로 변환하려면 어떻게 해야 합니까? 명령에서 자주 사용하는 것처럼 사용할 수 있는 --porcelain패턴 이 있습니까?grepgit

test-num:1:date:jan-2예: grep하려는 파일 로 가득 찬 폴더가 있습니다 . 이 파일에는 FAILURE:<some reason>또는 SUCCESS:<some reason>(무엇보다도)이 포함되어 있습니다. 특정 원인을 검색하고 나중에 처리하기 위해 파일 이름과 원인(텍스트 전체 라인이 가능함)을 저장하는 스크립트가 필요합니다. 출력은 코드를 실행할 수 있는 한 모든 유형의 데이터 구조가 될 수 있습니다.

답변1

grep --porcelainUNIX에서는 파일 이름의 특수 문자를 처리하는 것이 항상 나중에 고려된 사항이 아닙니다 . 다음과 같이 시도해 볼 수 있지만 효율성이 떨어지게 됩니다.

pattern='some pattern'
for file in ./*; do
    grep -- "$pattern" "$file" | while read -r line; do
        printf 'file: %s, line: %s\n' "$file" "$line"
    done
done

답변2

최신(-ish) 버전의 GNU grep에는 출력을 명확하게 만드는 옵션이 있지만 -Z대부분은 grep -lZ … | xargs -0. 여전히 작동하지만 쉘은 널 바이트를 처리하는 데 능숙하지 않으므로 이 출력을 구문 분석하는 데 어려움을 겪게 됩니다.

약간의 성능 저하가 있는 간단한 솔루션은 각 파일에 대해 개별적으로 grep을 실행하는 것입니다.

또 다른 해결책은 Perl이나 Python과 같은 언어를 사용하는 것입니다. Perl은 grep REGEX기본적으로 grep 시뮬레이션에 매우 능숙합니다  perl -ne '/REGEXP/ and print'.

그러나 출력이 실제로 모호하지 않다면 아마도 이것이 전혀 필요하지 않을 것입니다. 예를 들어 일치하는 줄에 콜론이 없으면 파일 이름은 줄에서 마지막 콜론까지의 모든 항목입니다. 일치하는 줄이 모두 SUCCESS또는로 시작하고 FAILURE해당 단어가 파일 이름에 나타나지 않으면 이를 사용하여 구분 기호 등을 찾을 수 있습니다.

1 줄 바꿈으로 끝나는 레코드 대신 Null로 끝나는 레코드를 필터링하는 데 사용되지 않는 한 null은 파일 이름 종결자와 결과 종결자입니다 . 출력은 여전히 ​​명확하지 않으며 대체 출력 레코드는 파일 이름과 출력의 일치하는 레코드입니다.-z-o

답변3

grep의 출력을 안전하게 사용하는 방법대본에서?

...출력은 어떤 유형이든 가능합니다.데이터 구조,코드를 실행할 수 있는 한 말이죠.

쉘 스크립트에는 실제로 데이터 구조가 없습니다. 배열이 있지만 그게 전부입니다. 출력을 배열로 안전하게 파이프하는 것은 쉽지 않습니다. (파일 이름할 수 있는개행 문자를 포함합니다. )

가장 좋은 방법은코드 실행쉘 스크립트에서 파일을 작업하는 방법은 나중에 사용하기 위해 파일 이름을 저장하는 대신 파일에 대해 코드를 실행하는 것입니다.

이렇게 하려면 다음을 사용하세요 find.

find somedir -type f -exec grep -q somepattern {} \; -exec somecommand {} \;

그러나 귀하의 질문을 더 자세히 읽어 보면 실제로는 원하지 않는 것 같습니다.코드 실행파일에서 특정 줄의 일부 텍스트 처리만 수행하려고 합니다. 이 경우 GNU Grep 옵션이 -z원하는 것일 수 있습니다. Sed 또는 Awk에 대한 지식과 함께 문제를 해결할 수 있습니다.


파일 명명 규칙을 변경하는 것이 현명할 수 있습니다.

관련 정보