패턴을 찾을 수 없는 경우 쉘 스크립트가 조기 종료되는 것을 방지하기 위한 `set -e` 및 `grep` 관용어

패턴을 찾을 수 없는 경우 쉘 스크립트가 조기 종료되는 것을 방지하기 위한 `set -e` 및 `grep` 관용어

도움이 필요합니다 - GNU/LINUX bash의 쉘 스크립팅 환경에서:

나는 항상 를 사용합니다 set -e. 항상 원하는 것은 아니지만 종료 상태가 패턴을 찾을 수 없음을 나타낼 때 grep스크립트 실행을 종료하는 것을 원합니다 .grep1

이 문제를 해결하려는 방법은 다음과 같습니다.

(I를 시도해보세요) 그런 식으로 grep을 호출
하면 미래의 관리자가 활성화할 때까지 원하는 동작을 얻을 수 있습니다 . 또한 나는 활성화하는 것을 좋아하므로 이것이 나에게 적합하지 않습니다.set +o pipefailgrep 'p' | wc -lpipefailpipefail

(2번 시도) 패턴과 일치하는 줄만
사용 sed하거나 인쇄한 다음 일치하는 줄을 사용하여 일치하는 패턴을 테스트하세요. to를 사용하는 것이 내 실제 문제에 대한 해결책인 것 같기 때문에 이 옵션이 마음에 들지 않습니다 .awkwcsedgrep

(시도 III)
이것은 내가 가장 좋아하지 않는 것입니다. 다음과 같습니다.set +e; grep 'p'; set-e

어떤 통찰력/관용구라도 대단히 감사하겠습니다. 감사합니다.

답변1

조건 에 grep을 넣을 수도 if있고, 종료 상태에 관심이 없다면 || true.

예: grep쉘 종료

$ bash
$ set -e
$ echo $$
33913
$ grep foo /etc/motd
$ echo $$
9233

해결 방법 1: 0이 아닌 종료 상태 삭제

$ bash
$ set -e
$ echo $$
34074
$ grep foo /etc/motd || true
$ echo $$
34074

해결 방법 2: 종료 상태를 명시적으로 테스트

$ if ! grep foo /etc/motd; then echo not found; fi
not found
$ echo $$
34074

Bash 매뉴얼 페이지 토론에서 set -e:

실패한 명령이 즉시 명령 목록의 일부인 경우 쉘이 종료되지 않습니다.하지만또는~까지 키워드, 테스트의 일부만약에또는일생예약어, 실행된 명령의 일부 &&또는나열된 마지막 명령 뒤의 명령은 제외&&또는, 마지막 명령을 제외한 파이프라인의 모든 명령 또는 반환 값이 다음과 같은 명령!.

답변2

명령이 실패할 경우 효과를 비활성화하려면 errexit다른 사람들이 말했듯이 명령을 조건문의 일부로 if/ elif및 사이에 사용 then하거나 while/ until및 논리 연산자 do뒤에 사용하는 것으로 충분합니다 .&&||

errexit종료 상태를 변경하지 않고 효과를 비활성화하는 표준 관용구는 다음과 같습니다.

cmd && true

그건 아직도 ​​돌아오지가짜cmd실패했지만 쉘을 종료하지 않는 경우 .

그러나 종종 당신이 원하는 것은 실패와 그 errexit영향을 무시하는 것입니다.

따라서 보다 정식적인 접근 방식은 다음과 같습니다.

cmd || true

이는 반환트루이성공 여부 cmd.

grep반품트루이입력 중 하나 이상의 라인이 일치하고 오류가 발생하지 않은 경우가짜그렇지 않으면.

일반적으로 다음 용도로 사용됩니다.

if grep -q pattern file; then
  echo at least one line of file matched the pattern
  do-something
fi

원하는 것이 있으면 출력이고 grep일치 항목이 없어도 상관하지 않으면 grep종료 상태를 무시할 수 있습니다.

grep pattern file || true

하지만 넌 잡지 못할 거야실수예를 들어 file열 수 없거나 정규식에 구문 오류가 있거나 grep해당 출력을 쓸 수 없는 경우입니다.

grep1불일치 및 오류의 경우 종료 상태가 사용되며, 발견되지 않은 경우 127로 설정되거나 종료된 경우 128보다 큰 숫자로 2설정될 수 있습니다 . 따라서 값을 기준으로 불일치와 오류를 명확하게 구분하고 다음을 사용하여 오류만 트리거할 수 있어야 합니다 .$?grep$?errexit

grep pattern file || [ "$?" -eq 1 ]

이는 반환트루이성공 하거나 grep일치하는 항목이 없으면 실패하면 종료됩니다 errexit( [불일치 이외의 오류) $?.1

set -o errexit그러나 일반적으로 매우 불안정한 오류 (일명 ) 에 의존하기보다는 적절한 오류 처리를 수행하는 것이 좋습니다 set -e. 다양한 실패 모드를 구별해야 하는 경우 grep다음을 수행할 수 있습니다.

die() { [ "$#" -eq 0 ] || printf>&2 '%s\n' "$@"; exit 1; }
grep pattern file
case $? in
  (0) echo OK, match;;
  (1) echo OK, no match;;
  (*) handle-error; die;;
esac

답변3

pipefail또한 서브셸을 사용하여 설정을 일시적으로 비활성화하거나 무시할 수도 있습니다.

( set +o pipefail ; grep 'p' ) | wc -l

또는

( grep 'p' || true ) | wc -l

또한 두 번째 경우에는 괄호가 필요하므로 |더 단단히 바인딩됩니다 .||

답변4

종료 상태에 관심이 있는 또 다른 옵션은 다음과 같습니다.

    FOUND=$(grep whatever here) || true     
    if [ -z $FOUND ]; then
      echo "not found"
    else
      echo "found"
    fi

관련 정보