“참이 아닌 경우”만드는 법?


317

true가 아닌 경우 echo명령을 실행 하고 싶습니다 cat /etc/passwd | grep "sysa".

내가 뭘 잘못하고 있죠?

if ! [ $(cat /etc/passwd | grep "sysa") ]; then
        echo "ERROR - The user sysa could not be looked up"
        exit 2
fi

7
는해야 !대괄호 안에 있지? 즉[ ! EXPR ]
acraig5075

7
@ acraig5075 어느 쪽이든 유효하지만이 문장에서 테스트 명령 (괄호가 무엇인지)은 전혀 필요하지 않습니다.
Charles Duffy

답변:


454

시험

if ! grep -q sysa /etc/passwd ; then

greptrue검색 대상을 찾은 경우 검색 대상을 찾지 못하면 반환 합니다 false.

따라서 NOT false== true입니다.

if 셸에서의 평가는 매우 유연하게 설계되었으며, 많은 경우 명령 체계가 필요하지 않습니다.

또한 코드를있는 그대로 살펴보면 $( ... )cmd-substitution 형식을 사용 하는 것이 좋지만 프로세스에서 무엇이 나오는지 생각해보십시오. 시도 echo $(cat /etc/passwd | grep "sysa")무슨 뜻인지 볼 수 있습니다. -c(count) 옵션을 사용하여 grep 한 다음 if ! [ $(grep -c "sysa" /etc/passwd) -eq 0 ] ; then어느 것이 작동하지만 다소 오래된 학교 를 통해 더 많은 것을 취할 수 있습니다 .

그러나 최신 쉘 기능 (산술 평가)을 사용할 수 있습니다.

if ! (( $(grep -c "sysa" /etc/passwd) == 0 )) ; then ...`

또한 c-lang 기반 비교 연산자 ==,<,>,>=,<=,%및 다른 몇 가지 를 사용하는 이점을 제공합니다 .

이 경우 Orwellophile의 의견에 따라 다음과 같이 산술 평가를 더 세분화 할 수 있습니다.

if ! (( $(grep -c "sysa" /etc/passwd) )) ; then ....

또는

if (( ! $(grep -c "sysa" /etc/passwd) )) ; then ....

마지막으로 이라는 상이Useless Use of Cat (UUOC) 있습니다. :-) 어떤 사람들은 위아래로 점프하고 고트 카를 외칠 것입니다! 그냥 grepcmd 줄에 파일 이름 을 사용할 수 있다고 말할 것입니다. 왜 필요하지 않을 때 추가 프로세스와 파이프 구성을 호출합니까? ;-)

이게 도움이 되길 바란다.


1
그것은 [내 대답에서 더 힘들어 (질문)에, 정말 오히려 바보 전부 stackoverflow.com/a/30400327/912236]를 grep "^$user:" /etc/passwd 검색 할 수있는 더 올바른 방법 / 것이다 etc / passwd에 incidently - grep -v어디 -v는 당신이 원하는 경우에 검색을 반전 의 혼란을 피하기 위해 ||
Orwellophile 2016 년

1
예, 문제를 가장 효율적으로 해결 한 다음 구체적인 질문에 대한 답변이 있습니다. 특정 질문에 대답하려고했습니다. 당신의 아이디어에 감사드립니다. 모두에게 행운을 빕니다.
shellter

1
당신의 답변을 고르지 않고, 꽤 즐거웠습니다. 난 그냥 통해 사용자 이름에 대한 적절한 경계 검사를 던져 것입니다. 그렇지 않으면 OP가 실제로 "sys"또는 그와 비슷한 것을 검색하면 그는 놀랄 것입니다. 도로 하나 더? (( $( cat file | grep regex | wc -l ) ? 0 : 1 ))
Orwellophile 2016 년

1
큰! 어떤 이유로 reqular "! grep -qs ..."가 / proc / mounts에서 작동하지 않고 정기적으로 떨어지는 USB 디스크가 Raspbian 4.9 커널에 마운트되었는지 확인하려고했습니다. 이것은 완벽하게 일을했습니다!
DocWeird

33

나는 그것이 다음과 같이 단순화 될 수 있다고 생각한다 :

grep sysa /etc/passwd || {
    echo "ERROR - The user sysa could not be looked up"
    exit 2
}

또는 단일 명령 행

$ grep sysa /etc/passwd || { echo "ERROR - The user sysa could not be looked up"; exit 2; }


4
멋지지만 "자체 문서화"되어 있기 때문에 Mr. shellter 답변을 선호합니다. 프로그래머 의도가 더 "판독 가능"합니다.
0zkr PM

1
나는이 버전을 좋아한다. 인쇄를 위해 1>&2끝에 추가하는 것은 어떻습니까? echostderr
Julien

2
@ 0zkrPM 그러나 Bourne 셸에서는 셸터 버전이 작동하지 않습니다. 당신은 얻을!: not found
ceving

1
'grep이와 같이 사용할 때는 출력 리디렉션을 피하십시오 . -q출력을 억제합니다.
tbc0

8

내가 뭘 잘못하고 있죠?

$(...)종료 상태가 아닌 값을 보유 하므로이 방법이 잘못되었습니다. 그러나이 특별한 경우 sysa에는 테스트 진술이 실현되도록 인쇄 되기 때문에 실제로 작동 합니다. 그러나 종료 코드가 0이더라도 명령이 stdout에 아무것도 쓰지 않기 때문에 if ! [ $(true) ]; then echo false; fi항상 인쇄 됩니다. 그렇기 때문에이를 다시 설명해야 합니다.falsetrueif ! grep ...; then

대안은입니다 cat /etc/passwd | grep "sysa" || echo error. 편집 : 알렉스가 지적한 바와 같이, 고양이가 여기에 쓸모가 : grep "sysa" /etc/passwd || echo error.

다소 혼란스러워 다른 답변을 찾았습니다. 이것이 누군가를 돕기를 바랍니다.


1

지원하는 유닉스 시스템 (macOS가 아닌 것) :

if getent passwd "$username" >/dev/null; then
    printf 'User %s exists\n' "$username"
else
    printf 'User %s does not exist\n' "$username"
fi 

이는 사용중인 디렉토리 서비스 (YP / NIS 또는 LDAP 등) 및 로컬 비밀번호 데이터베이스 파일을 조회한다는 이점이 있습니다.


문제 grep -q "$username" /etc/passwd는 그러한 사용자가 없을 때 거짓 긍정을 주지만 다른 것과 패턴이 일치한다는 것입니다. 파일의 다른 부분에 부분적이거나 정확하게 일치하는 경우 발생할 수 있습니다.

예를 들어, 내 passwd파일에는 다음과 같은 줄이 있습니다.

build:*:21:21:base and xenocara build:/var/empty:/bin/ksh

이 같은 것들에 유효한 일치 도발 것 cara하고 enoc내 시스템에 이런 사용자가 없더라도 등.

A에 대한 grep해결책이 정확하려면 제대로 분석해야합니다 /etc/passwd파일 :

if cut -d ':' -f 1 /etc/passwd | grep -qxF "$username"; then
    # found
else
    # not found
fi

... 또는-구분 된 첫 번째 :필드 에 대한 다른 유사한 테스트 .


@SDsolar 아마도이 경우 코드가 실행되지 않을 것입니다 bash.
Kusalananda

1

예를 들어 대답은 다음과 같습니다.

데이터 로거가 온라인 상태인지 확인하기 위해 cron15 분마다 다음과 같은 스크립트가 실행됩니다.

#!/bin/bash
#
if ! ping -c 1 SOLAR &>/dev/null
then
  echo "SUBJECT:  SOLAR is not responding to ping" | ssmtp abc@def.com
  echo "SOLAR is not responding to ping" | ssmtp 4151112222@txt.att.com
else
  echo "SOLAR is up"
fi
#
if ! ping -c 1 OUTSIDE &>/dev/null
then
  echo "SUBJECT:  OUTSIDE is not responding to ping" | ssmtp abc@def.com
  echo "OUTSIDE is not responding to ping" | ssmtp 4151112222@txt.att.com
else
  echo "OUTSIDE is up"
fi
#

http://www.SDsolarBlog.com/montage 의 몽타주에서 볼 수있는 각 데이터 로거마다


참고로 &>/dev/null오류를 포함하여 명령의 모든 출력을/dev/null

(조건부 exit status에는 ping명령 만 필요 )

참고로 cron작업이 실행되므로 스크립트 에서 root사용할 필요가 없습니다 .sudo pingcron

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