「真でない場合」の作り方


317

私が持っているしたい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
!はブラケットの中に入れるべきではありませんか?ie[ ! EXPR ]
acraig5075 2012年

7
@ acraig5075どちらの方法でも有効ですが、このステートメントではテストコマンド(角かっことは何か)はまったく必要ありません。
Charles Duffy

回答:


455

試す

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-lineでファイル名をとることができるので、必要がないときに追加のプロセスとパイプ構造を呼び出すのはなぜですか?;-)

これがお役に立てば幸いです。


1
これは、[私の答えから、はるかに困難(質問)に、実際にはむしろ愚かなすべてだstackoverflow.com/a/30400327/912236]を grep "^$user:" /etc/passwd検索するためのより正確な方法/だろうetc / passwdファイルincidently - grep -vどこ-vは、あなたが望んでいた場合は、検索を反転||の混乱を避けるために
Orwellophile 2015年

1
はい、問題を最も効率的に解決し、特定の質問に答えます。特定の質問に答えようとしました。あなたのアイデアをありがとう。皆さんお元気で。
シェルター、2015年

1
あなたの答えを選ぶのではなく、かなり楽しんだ。私はちょうど私がユーザー名に適切に制限されたチェックを投入します、さもなければ、OPが本当に「sys」またはそのようなものを検索する場合、彼はかなり驚きを得るでしょう。道路のためにもう一つ? (( $( cat file | grep regex | wc -l ) ? 0 : 1 ))
Orwellophile 2015年

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
いいですが、「自己文書化されている」ので、プログラマーの意図がより「読みやすい」ので、シェルター氏の答えを好みます。
0zkr PM '09 / 09/18

1
このバージョンが好きです。1>&2最後に追加しechoて印刷するのはstderrどうですか?
ジュリアン

2
@ 0zkrPMしかし、shellterバージョンはBourneシェルでは機能しません。取得します!: not found
2016年

1
'grepこのように使用する場合は、出力のリダイレクトを避けてください。-q出力を抑制します。
tbc0

8

何が悪いのですか?

$(...)は、終了ステータスではなく値を保持するため、このアプローチは間違っています。ただし、この特定のケースでは、実際に機能しsysaます。印刷されるため、テストステートメントが実現します。ただし、コマンドはstdoutに何も書き込まないため(終了コードが0であっても)、if ! [ $(true) ]; then echo false; fi常に印刷さfalsetrueます。そのため、次のように言い換える必要がありますif ! grep ...; then

代替案は次のようになりますcat /etc/passwd | grep "sysa" || echo error。編集:アレックスが指摘したように、猫はここでは役に立たないgrep "sysa" /etc/passwd || echo error

やや混乱する他の回答が見つかりました。これが誰かの役に立つことを願っています。


1

これをサポートするUnixシステム(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

私のシステムにそのようなユーザーがいない場合でも、これによりcaraenocなどに有効な一致が引き起こされます。

以下のためにgrep解決策が正しいことを、あなたは適切に解析する必要があります/etc/passwdファイルを:

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

...または最初の- :区切りフィールドに対する他の同様のテスト。


@SDsolar bashその場合、コードはおそらく実行されません。
Kusalananda 2017年

1

例としてここに答えがあります:

データロガーがオンラインであることを確認するためにcron、次のようなスクリプトが15分ごとに実行されます。

#!/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 statuspingコマンドののみを必要とします)

また参考までに、cronジョブはスクリプトでroot使用する必要がないので実行されるので注意してください。sudo pingcron

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.