Ngăn chặn grep thoát ra trong trường hợp nomatch


29

Kịch bản này không lặp lại "sau":

#!/bin/bash -e

echo "before"

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

echo "after"
exit

Nó cũng sẽ nếu tôi loại bỏ -etùy chọn trên dòng shebang, nhưng tôi muốn giữ nó để kịch bản của tôi dừng lại nếu có lỗi. Tôi không coi grep không tìm thấy lỗi nào phù hợp. Làm thế nào tôi có thể ngăn nó thoát ra đột ngột như vậy?


Đây là một quan sát chỉ có ý nghĩa để xem xét. Có lẽ logic của kịch bản này nên được suy nghĩ lại. Nếu nó không quan trọng để tìm chuỗi, tại sao tìm kiếm nó? Định nghĩa của grep là người ta đưa ra quyết định dựa trên sự hiện diện hay vắng mặt của một chuỗi. Nếu bạn không quan tâm một trong hai cách, thì nó không quan trọng. Ngoài ra, có vẻ như tiền -egiả định bạn quan tâm: rất nhiều đến nỗi mọi vấn đề đều là thảm họa.
Andrew Falanga

2
@AndrewFalanga Tôi cũng quan tâm theo cách này vì tôi thực sự đang phân tích nội dung var=$(complex command | grep complex_pattern)có thể là null (trong trường hợp đó chương trình của tôi không nên chấm dứt). Đây chỉ là một kịch bản được đun sôi khiến vấn đề xảy ra. Không có lỗ đen siêu hình trong logic ở đây, phải không? ;)
iago-lito

Bây giờ biết rằng bạn có ý định nắm bắt đầu ra sẽ làm rõ một số điều. Như đã trình bày, nó đã gây nhầm lẫn cho tôi.
Andrew Falanga

Câu trả lời:


33
echo "anything" | grep e || true

Giải trình:

$ 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

"||" có nghĩa là "hoặc". Nếu phần đầu tiên của lệnh "fail" (có nghĩa là "grep e" trả về mã thoát khác không) thì phần sau "||" được thực thi, thành công và trả về 0 dưới dạng mã thoát ( trueluôn trả về 0).


3
Một phiên bản ngắn hơn một chút mà không quay lên /bin/truelà: command || :(vì vậy trong trường hợp của bạn, set -e; grep 'needle' haystack || :).
DopeGhoti

1
@DopeGhoti, trueđược tích hợp sẵn trong một số vỏ (ít nhất là bash 4.3trên RHEL)
iruvar

3
Không hợp lệ vì nếu lệnh đầu tiên thất bại, nó sẽ ẩn lỗi. Một giải pháp đúng sẽ trả về giá trị khác không nếu lệnh đầu tiên trong đường ống bị lỗi.
sorin

11

Một cách mạnh mẽ để nhắn tin an toàn và tùy chọn 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

Theo hướng dẫn posix , mã thoát 1 có nghĩa là không có dòng nào được chọn và> 1 có nghĩa là lỗi.


1
Đây phải là câu trả lời được chấp nhận, vì nó chỉ chặn mã thoát cảnh báo (1) nếu grep không tìm thấy gì, nhưng nó lại chuyển sang các lỗi thực sự (mã thoát> 1). Các giải pháp khác ở đây luôn luôn ngăn chặn các lỗi thực sự, thường là xấu.
HaroldFinch

7

Một tùy chọn khác là thêm một lệnh khác vào đường ống - một lệnh không bị lỗi:

echo "anything" | grep e | cat

Bởi vì catbây giờ là lệnh cuối cùng trong đường ống, đó là trạng thái thoát cat, chứ không phải grep, sẽ được sử dụng để xác định xem đường ống có bị lỗi hay không.



3

Dung dịch

#!/bin/bash -e

echo "before"

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

echo "after"
exit

Giải trình

set -e hoặc là set -o errexit

Thoát ngay lập tức nếu một đường ống (có thể bao gồm một lệnh đơn giản ), danh sách hoặc lệnh ghép (xem SHELL GRAMMARở trên), thoát với trạng thái khác không. Shell không thoát nếu lệnh bị lỗi là một phần của danh sách lệnh ngay sau một whilehoặc một untiltừ khóa, một phần của kiểm tra theo các từ ifhoặc elifdành riêng, một phần của bất kỳ lệnh nào được thực thi trong một danh sách &&hoặc ||ngoại trừ lệnh theo sau lệnh cuối cùng &&hoặc ||bất kỳ lệnh trong một đường ống nhưng cuối cùng hoặc nếu giá trị trả về của lệnh đang được đảo ngược với!. Nếu một lệnh ghép không phải là một lớp con trả về trạng thái khác không vì một lệnh bị lỗi trong khi -ebị bỏ qua, shell sẽ không thoát. Một cái bẫy trên ERR, nếu được đặt, được thực thi trước khi thoát vỏ. Tùy chọn này áp dụng cho môi trường shell và từng môi trường shell con riêng biệt (xem COMMAND EXECUTION ENVIRONMENTbên trên) và có thể khiến các lớp con thoát ra trước khi thực hiện tất cả các lệnh trong lớp con.

Thêm vào đó, :là lệnh không có hiệu lực trong Bash.

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.