grep 명령의 결과로 수신 된 각 줄을 처리하는 방법


152

다음과 같이 grep 명령을 실행 한 후 파일에서 여러 줄을 검색했습니다 .

var=`grep xyz abc.txt`

결과적으로 xyz로 구성된 10 줄이 있다고 가정 해 봅시다.

이제 grep 명령의 결과로 얻은 각 줄을 처리해야합니다. 이를 위해 어떻게 진행합니까?


6
여기에 어떤 대답도 grep -o이런 종류의 힘을 언급하지 않습니다. -o플래그는 다시 줄 것이다 에만 출력을 한 줄에 하나의 일치와 일치하는 텍스트를. (완전하지는 않으므로 echo aaa |grep 'a*'"aaa"만 제공하고 "", "a"및 "aa"의 세 부분 일치 항목은 생략합니다.
Adam Katz

답변:


269

쉬운 방법 중 하나는 출력을 변수에 저장하지 않고 while / read 루프를 사용하여 직접 반복하는 것입니다.

다음과 같은 것 :

grep xyz abc.txt | while read -r line ; do
    echo "Processing $line"
    # your code goes here
done

정확히 당신이 무엇을 추구하는지에 따라이 체계에는 변형이 있습니다.

루프 내부의 변수를 변경해야하고 외부에서 변경 사항을 볼 수 있어야하는 경우 fedorqui의 답변에 설명 된대로 프로세스 대체를 사용할 수 있습니다 .

while read -r line ; do
    echo "Processing $line"
    # your code goes here
done < <(grep xyz abc.txt)

xyz와 함께 줄이 없다면?
XYZ_Linux 12

그런 다음 아무 일도 일어나지 않으며 루프가 실행되지 않습니다.
Mat

13
이 방법의 문제점은 (파이프 때문에) 루프 내부의 모든 것이 서브 쉘에 있다는 것입니다. 따라서 루프 동안 루프 외부에 정의 된 변수를 설정하면 루프 후에 값을 사용할 수 없습니다!
David Doria

3
@David : 우려 사항을 해결하기위한 대안을 제공했습니다. (fedorqui도 이미 그것을 다루었습니다.)
Mat

그 마지막 줄 출력의 줄 바꿈 종료되지 않는 명령의 경우, 필요한 것 : while read p || [[ -n $p ]]; do ...(에서 차용 stackoverflow.com/questions/1521462/... )
오핫 슈나이더

21

소위 프로세스 대체를 사용하여 명령 while read결과에 의해 제공되는 다음 루프를 수행 할 수 있습니다 grep.

while IFS= read -r result
do
    #whatever with value $result
done < <(grep "xyz" abc.txt)

이런 식으로 결과를 변수에 저장할 필요는 없지만 출력을 루프에 직접 "주입"할 수 있습니다.


의 사용을 참고 IFS=하고 read -rBashFAQ / 001의 권장 사항에 따라 : I 파일 (데이터 스트림, 변수) 라인 별 (및 / 또는 필드 단위)를 읽을 수 있습니까? :

-r 옵션을 읽으면 백 슬래시 해석을 방지 할 수 있습니다 (보통 백 슬래시 줄 바꿈 쌍으로 사용, 여러 줄을 넘거나 구분자를 이스케이프하기 위해 사용) 이 옵션이 없으면 입력에서 이스케이프 처리되지 않은 백 슬래시가 삭제됩니다. 거의 항상 -r 옵션을 read와 함께 사용해야합니다.

위의 시나리오에서 IFS =는 선행 및 후행 공백의 트리밍을 방지합니다. 이 효과를 원하면 제거하십시오.

프로세스 대체와 관련하여 bash 해커 페이지에 설명되어 있습니다 .

프로세스 대체는 프로세스의 입력 또는 출력 (일부 명령 시퀀스)이 임시 파일로 나타나는 리디렉션의 한 형태입니다.


좋아, 나는 for버전을 쳤다 . stackoverflow.com/a/14588210/1983854 에서 "${$(grep xyz abc.txt)[@]}"와 같이 루프를 시도 했지만 실패했습니다 . 그래서 나는 첫 번째 버전을 떠납니다.
fedorqui 'SO 중지 피해'

1
명령 대체에 매개 변수 확장을 적용 할 수 없습니다 ( zsh이러한 종류의 중첩이 작동하는을 사용하지 않는 한 ).
chepner

이 관용구의 한 가지 가능한 문제점은 루프 내부의 어떤 것이 표준 입력에서 읽으려고하면 파일의 일부를 얻게된다는 것입니다. 이 가능성을 피하기 위해 stdin이 아닌 파일 설명자 3을 통해 파일을 보내고 싶습니다. 그냥 사용 while IFS= read -r result <&3하고done 3< <(grep ...
Gordon Davisson

8

grep + 대신에 awk를 사용하는 것이 좋습니다.

awk '$0~/xyz/{ //your code goes here}' abc.txt


1
에서 찾은 줄을 //your code goes here어떻게 참조 하시겠습니까?
user857990

2
@ user857990 AWK에서 전체 줄이 $ 0으로 표시됩니다.
Julien Grenier

2

--line-buffered grep 옵션을 사용하여 반복하지 않으면 :

your_command | grep --line-buffered "your search"

모든 "api"관련 라우트를 grep하기 위해 Symfony PHP Framework 라우터 디버그 명령 출력을 사용하는 실제 예 :

php bin/console d:r | grep --line-buffered "api"

your_command가 오래 실행되는 경우에만 작동하는 유일한 솔루션입니다 (예 tail -f some.log
:)

0

종종 처리 순서는 중요하지 않습니다. 이 상황에서 GNU Parallel이 만들어졌습니다.

grep xyz abc.txt | parallel echo do stuff to {}

처리하는 것이 더 비슷하다면 :

grep xyz abc.txt | myprogram_reading_from_stdin

그리고 myprogram다음 실행할 수 있습니다 느리다 :

grep xyz abc.txt | parallel --pipe myprogram_reading_from_stdin

0

while / read 루프를 사용하여 grep 결과를 반복하십시오. 처럼:

grep pattern filename.txt | while read -r line ; do
    echo "Matched Line:  $line"
    # your code goes here
done

0

하나의 라이너를 찾는 사람들을 위해 :

grep xyz abc.txt | while read -r line; do echo "Processing $line"; done
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.