일치하지 않는 경우 grep이 종료되지 않도록 방지


29

이 스크립트는 "after"를 반향하지 않습니다.

#!/bin/bash -e

echo "before"

echo "anything" | grep e # it would if I searched for 'y' instead

echo "after"
exit

또한 -eshebang 행 에서 옵션을 제거 하면 오류가있을 때 스크립트가 중지되도록 유지하고 싶습니다. grep이 일치하지 않는 것을 오류로 간주하지 않습니다. 갑작스럽게 종료되지 않도록하려면 어떻게해야합니까?


이것은 단지 고려를위한 관찰입니다. 아마도이 스크립트의 논리는 다시 생각해야합니다. 문자열을 찾는 것이 중요하지 않은 경우 왜 문자열을 검색합니까? grep의 정의는 문자열의 존재 여부에 따라 의사 결정을 내리는 것입니다. 어느 쪽이든 상관하지 않는다면 중요하지 않습니다. 또한, -e당신이 돌보는 것을 전제로하는 것처럼 보일 것입니다 : 너무 많은 문제 는 치명적입니다.
Andrew Falanga

2
@AndrewFalanga 실제로 내용 var=$(complex command | grep complex_pattern)이 null 일 수 있는 내용을 분석하고 있기 때문에 어느 쪽이든주의를 기울입니다 (이 경우 프로그램이 종료되지 않아야 함). 이것은 문제가 발생하는 정리 된 스크립트입니다. 논리에 형이상학 적 블랙홀이 없습니다. ;)
iago-lito

출력을 캡처하려고한다는 것을 알면 몇 가지 사항이 명확 해집니다. 제시된 바와 같이, 그것은 혼란 스러웠다.
Andrew Falanga

답변:


33
echo "anything" | grep e || true

설명:

$ echo "anything" | grep e
### error
$ echo $?
1
$ echo "anything" | grep e || true
### no error
$ echo $?
0
### DopeGhoti's "no-op" version
### (Potentially avoids spawning a process, if `true` is not a builtin):
$ echo "anything" | grep e || :
### no error
$ echo $?
0

"||" "또는"을 의미합니다. 명령의 첫 번째 부분 "fails"( "grep e"가 0이 아닌 종료 코드를 리턴 함을 의미 함) 인 경우 "||"다음 부분 종료 코드로 실행되고 성공하고 0을 리턴합니다 ( true항상 0을 리턴 함).


3
회전하지 않는 약간 짧은 버전은 다음과 /bin/true같습니다 command || :(따라서 set -e; grep 'needle' haystack || :).
DopeGhoti

1
@DopeGhoti는 trueA가 내장 된 일부 껍질에 (적어도에 bash 4.3RHEL에)
iruvar

3
첫 번째 명령이 실패하면 오류를 숨기므로 유효하지 않습니다. 파이프의 첫 번째 명령이 실패하면 올바른 솔루션이 0이 아닌 값을 반환해야합니다.
소린

11

안전하고 선택적으로 grep 메시지를 전달 하는 강력한 방법 :

echo something | grep e || [[ $? == 1 ]] ## print 'something', $? is 0
echo something | grep x || [[ $? == 1 ]] ## no output, $? is 0
echo something | grep --wrong-arg e || [[ $? == 1 ]] ## stderr output, $? is 1

posix manual 에 따르면 , 종료 코드 1은 선택된 행이 없음을 의미하고> 1은 오류를 의미합니다.


1
grep이 아무것도 찾지 못하면 경고 종료 코드 (1) 만 억제하지만 실제 오류 (종료 코드> 1)를 전달하므로 허용되는 응답이어야합니다. 여기의 다른 솔루션은 항상 실제 오류를 억제하며 이는 일반적으로 좋지 않습니다.
HaroldFinch

7

또 다른 옵션은 파이프 라인에 실패하지 않는 다른 명령을 추가하는 것입니다.

echo "anything" | grep e | cat

cat이제 파이프 라인의 마지막 명령 이므로 파이프 라인의 실패 여부를 판별하는 데 사용되는 종료 상태가 cat아닌의 종료 상태입니다 grep.



3

해결책

#!/bin/bash -e

echo "before"

echo "anything" | grep e || : # it would if I searched for 'y' instead

echo "after"
exit

설명

set -e 또는 set -o errexit

파이프 라인 (단일 단순 명령 으로 구성 될 수 있음 ), list 또는 복합 명령 ( SHELL GRAMMAR위 참조 )이 0이 아닌 상태로 종료 되면 즉시 종료 하십시오 . 실패 명령이 즉시 다음 명령 목록의 일부인 경우 쉘은 종료되지 않습니다 while또는 until키워드, 다음 시험의 일부 if또는 elif예약어하는 실행 모든 명령의 일부 &&또는 ||최종 다음 명령을 제외 목록 &&또는 ||어떤, 파이프 라인의 명령이지만 마지막 명령 또는 명령의 반환 값이 반전되는 경우!. 서브 쉘 이외의 복합 명령 -e이 무시되는 동안 명령이 실패하여 0이 아닌 상태를 리턴 하면 쉘이 종료되지 않습니다. ERR설정된 경우 트랩이 트랩 이 종료되기 전에 실행됩니다. 이 옵션은 셸 환경과 각 하위 셸 환경에 별도로 적용되며 ( COMMAND EXECUTION ENVIRONMENT위 참조 ) 하위 셸 에서 모든 명령을 실행하기 전에 하위 셸 이 종료 될 수 있습니다.

또한 :Bash의 효과 없음 명령입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.