Làm thế nào để tạo ra nếu không đúng điều kiện?


317

Tôi muốn echothực hiện lệnh khi cat /etc/passwd | grep "sysa"không đúng.

Tôi đang làm gì sai?

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

7
Không nên !ở trong ngoặc? tức là[ ! EXPR ]
acraig5075

7
@ acraig5075 dù sao thì nó cũng hợp lệ, nhưng không cần lệnh kiểm tra (đó là dấu ngoặc) trong câu lệnh này.
Charles Duffy

Câu trả lời:


455

thử

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

greptrả về truenếu nó tìm thấy mục tiêu tìm kiếm và falsenếu nó không.

Vậy KHÔNG false== true.

if đánh giá trong shell được thiết kế rất linh hoạt và nhiều lần không yêu cầu chuỗi lệnh (như bạn đã viết).

Ngoài ra, nhìn vào mã của bạn, việc bạn sử dụng $( ... )hình thức thay thế cmd sẽ được khen ngợi, nhưng hãy nghĩ về những gì sắp diễn ra. Hãy thử echo $(cat /etc/passwd | grep "sysa")xem tôi muốn nói gì Bạn có thể thực hiện điều đó hơn nữa bằng cách sử dụng -ctùy chọn (đếm) để grep và sau đó thực hiện if ! [ $(grep -c "sysa" /etc/passwd) -eq 0 ] ; thencông việc nào nhưng trường học khá cũ.

NHƯNG, bạn có thể sử dụng các tính năng hệ vỏ mới nhất (đánh giá số học) như

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

cũng cung cấp cho bạn lợi ích của việc sử dụng các toán tử so sánh dựa trên c-lang ==,<,>,>=,<=,%và có thể một số khác.

Trong trường hợp này, theo nhận xét của Orwellophile, việc đánh giá số học có thể được giảm xuống hơn nữa, như

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

HOẶC LÀ

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

Cuối cùng, có một giải thưởng được gọi là Useless Use of Cat (UUOC). :-) Một số người sẽ nhảy lên nhảy xuống và khóc gothca! Tôi sẽ chỉ nói rằng grepcó thể lấy tên tệp trên dòng cmd của nó, vậy tại sao lại gọi thêm các quy trình và công trình đường ống khi bạn không phải làm vậy? ;-)

Tôi hi vọng cái này giúp được.


1
Thực sự khá là ngớ ngẩn, từ câu trả lời của tôi đến một câu hỏi khó hơn ( stackoverflow.com/a/30400327/912236] grep "^$user:" /etc/passwd sẽ là cách chính xác hơn để tìm kiếm / etc / passwd - grep -vnơi -v đảo ngược tìm kiếm nếu bạn muốn để tránh sự lộn xộn của | |
Orwellophile

1
vâng, có cách giải quyết vấn đề hiệu quả nhất, và sau đó là trả lời câu hỏi cụ thể. Tôi đã cố gắng trả lời câu hỏi cụ thể. Cảm ơn ý tưởng của bạn. Chúc mọi người may mắn.
shellter

1
không chọn câu trả lời của bạn, khá thích chúng. Tôi chỉ cần thông qua một kiểm tra giới hạn chính xác về tên người dùng, nếu OP thực sự tìm kiếm trên "sys" hoặc somesuch, anh ta sẽ khá ngạc nhiên. Một cái nữa cho đường? (( $( cat file | grep regex | wc -l ) ? 0 : 1 ))
Orwellophile

1
Tuyệt quá! Vì một số lý do, yêu cầu "! Grep -qs ..." không hoạt động với / Proc / mount và cố gắng tìm hiểu xem đĩa USB bị rơi thường xuyên có được gắn trên kernel Raspbian 4.9 không. Điều này đã làm công việc hoàn hảo!
Docweird

33

Tôi nghĩ rằng nó có thể được đơn giản hóa thành:

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

hoặc trong một dòng lệnh

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


4
Đẹp, nhưng tôi thích câu trả lời của Mr. shellter hơn là "tự ghi lại", là "dễ đọc" hơn ý định của lập trình viên.
0zkr PM

1
Tôi thích phiên bản này. Điều gì về việc thêm 1>&2vào cuối của bạn echođể in trên stderr?
Julien

2
@ 0zkrPM Nhưng phiên bản shellter không hoạt động trong shell Bourne. Bạn sẽ nhận được!: not found
ceving 14/03/2016

1
Tránh chuyển hướng đầu ra khi sử dụng 'grepnhư thế này. -qtriệt tiêu đầu ra.
tbc0

8

Tôi đang làm gì sai?

$(...)giữ giá trị , không phải trạng thái thoát, đó là lý do tại sao phương pháp này sai. Tuy nhiên, trong trường hợp cụ thể này, nó thực sự hoạt động vì sysasẽ được in ra để làm cho tuyên bố kiểm tra trở thành sự thật. Tuy nhiên, if ! [ $(true) ]; then echo false; fisẽ luôn in falsetruelệnh không ghi bất cứ điều gì vào thiết bị xuất chuẩn (mặc dù mã thoát là 0). Đó là lý do tại sao nó cần phải được rephras if ! grep ...; then.

Một sự thay thế sẽ là cat /etc/passwd | grep "sysa" || echo error. Chỉnh sửa: Như Alex đã chỉ ra, con mèo là vô dụng ở đây : grep "sysa" /etc/passwd || echo error.

Tìm thấy những câu trả lời khác khá khó hiểu, hy vọng điều này sẽ giúp được ai đó.


1

Trên các hệ thống Unix hỗ trợ nó (dường như không phải macOS):

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

Điều này có lợi thế là nó sẽ truy vấn bất kỳ dịch vụ thư mục nào có thể đang sử dụng (YP / NIS hoặc LDAP, v.v.) và tệp cơ sở dữ liệu mật khẩu cục bộ.


Vấn đề grep -q "$username" /etc/passwdlà nó sẽ cho kết quả dương tính giả khi không có người dùng như vậy, nhưng một cái gì đó khác phù hợp với mẫu. Điều này có thể xảy ra nếu có một phần khớp hoặc chính xác ở một nơi khác trong tệp.

Ví dụ, trong passwdtập tin của tôi , có một dòng nói

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

Điều này sẽ gây ra một trận đấu hợp lệ trên những thứ như caraenocvv, mặc dù không có người dùng như vậy trên hệ thống của tôi.

Để grepgiải pháp được chính xác, bạn sẽ cần phân tích đúng /etc/passwdtệp:

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

... Hoặc bất kỳ thử nghiệm tương tự nào khác đối với trường đầu tiên được phân định :.


@SDsolar Mã của bạn có thể không được thực thi bashtrong trường hợp đó.
Kusalananda

1

Đây là một câu trả lời bằng ví dụ:

Để đảm bảo logger dữ liệu đang trực tuyến, một đoạn cronscript chạy cứ sau 15 phút như thế này:

#!/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
#

... và cứ thế cho mỗi bộ ghi dữ liệu mà bạn có thể thấy trong đoạn phim tại http://www.SDsolarBlog.com/montage


FYI, sử dụng &>/dev/nullchuyển hướng tất cả đầu ra từ lệnh, bao gồm cả lỗi, để/dev/null

(Câu điều kiện chỉ đòi hỏi exit statuscủa pinglệnh)

Ngoài ra FYI, lưu ý rằng vì các croncông việc chạy như rootkhông cần sử dụng sudo pingtrong một crontập lệnh.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.