2012-01-22 20 views
23

Tại sao câu lệnh if sau đây thành công?

if $(ps aux | grep -q "bla bla") ; then echo "found" ; fi 
+4

Nếu bạn chạy 'ps aux | grep "bla bla" 'bạn sẽ thấy tại sao ... –

+0

Xem thêm [câu hỏi này] (http://stackoverflow.com/questions/8965887/command-substitution-in-if-statement-condition). –

+3

'nếu pgrep -f" bla bla "; sau đó echo "tìm thấy"; fi' – jordanm

Trả lời

32

Vì chính quy trình grep đang được trả lại ps. Bạn có thể "lừa" grep không phù hợp với bản thân bằng cách xung quanh một trong những nhân vật tìm kiếm trong một lớp nhân vật [ ] mà không thay đổi các chức năng: Chỉ cần làm:

if ps aux | grep -q "[b]la bla" ; then echo "found" ; fi 

Ngoài ra, việc sử dụng thay thế tiến trình $() là không cần thiết. Các if sẽ làm việc trên sự thành công của lệnh cuối cùng trong chuỗi ống, đó là những gì bạn muốn.

Note: Lý do lừa lớp nhân vật làm việc là do ps đầu ra vẫn có dấu ngoặc lớp nhân vật nhưng khi grep đang xử lý chuỗi tìm kiếm, nó sử dụng các dấu ngoặc như cú pháp chứ không phải là một chuỗi cố định để phù hợp.

+0

go go downvoter tiện ích – SiegeX

+0

Có một downvoter nối tiếp ra khỏi đó ..: P –

+0

Nice trick! Cảm ơn! –

7

quy trình 'grep' đã chạy vào thời điểm ps chạy, do đó đầu ra ps bao gồm nó.

Hãy thử sử dụng pgrep để thay thế.

pgrep là chính xác cho mục đích này:

if pgrep "bla bla" ; then echo "found" ; fi

+0

Ông Downvoter, tôi đã chỉnh sửa câu trả lời của tôi để rõ ràng hơn. Xin vui lòng xem nếu nó có vẻ tốt hơn bây giờ. Ta – laher

1

Bạn cần phải lọc ra các quá trình đó là grep ping cho 'bla bla':

$ if ps aux | grep -v 'grep' | grep -q 'bla bla'; then 
    echo 'Found' 
fi 
+0

bạn không muốn v-grep sau grep đích? (Nếu tôi downvote, tôi nói tại sao). – shellter

+0

Tôi cũng bị giảm giá hai lần mà không cần giải thích. Tôi nghĩ rằng ai đó đang downvoting rất tự do về câu hỏi này ... – laher

+0

@ amir75: trông thích tất cả các downvotes đã biến mất (một lần nữa không có lời giải thích!) ;-) Chúc may mắn cho tất cả. – shellter

8

Nếu bạn grep đầu ra từ ps aux, bạn sẽ luôn nhận được một quá trình hiển thị lệnh trước đó của bạn. Để khắc phục điều này, bạn có thể kết nối đầu ra thành grep hai lần, một lần để loại bỏ dòng có "grep" trong nó, và một lần nữa cho quá trình tìm kiếm của bạn.

 
ps aux | grep -v "grep" | grep "Finder" 
2

$( là một chút nhỏ có liên quan và thay đổi ý nghĩa một chút. Mặc dù trong trường hợp này, bởi vì không bao giờ có bất kỳ đầu ra nào từ grep -q, bạn chỉ có thể thoát khỏi số $(. Có thể bạn muốn bắt đầu với một cái gì đó tương tự (như đã chỉ ra bởi những người khác):

if ps aux | grep -v 'grep' | grep -q 'bla bla'; then 
    echo 'Found' 
fi 

Dù sao, bạn bắt đầu với

if $(ps aux | grep -q "bla bla") ; then echo "found" ; fi 

Với $(, lệnh bên trong $() được thực hiện và sản lượng mà lệnh được sử dụng như là dòng lệnh cho lệnh bên ngoài.Làm bốn thí nghiệm:

# if $(echo nonexistant ; true) ; then echo "found" ; fi 
nonexistant: command not found 

# if $(echo nonexistant ; false) ; then echo "found" ; fi 
nonexistant: command not found 

# if $(echo ; true) ; then echo "found" ; fi 
found 

# if $(echo ; false) ; then echo "found" ; fi 

Vì vậy, theo này, bạn sẽ đưa ra được found nếu cả hai điều kiện tổ chức:

  • Lệnh bên trong $() tạo không có đầu ra
  • lệnh đã thành công

Điều này gợi ý rằng ps aux | grep -q "bla bla" đã thành công và không tạo đầu ra. Không có gì ngạc nhiên khi grep -q không tạo đầu ra. Đó là những gì mà -q dành cho. Vì vậy, do đó, lệnh của bạn phải có một trạng thái thực sự, ngụ ý rằng grep đã thành công trong việc tìm một kết quả phù hợp. Chúng tôi biết rằng grep sẽ luôn tìm thấy kết quả phù hợp trong trường hợp này, vì danh sách các quy trình từ ps sẽ bao gồm grep chính nó; grep sẽ luôn tìm thấy chính nó.

+0

giải thích 'bùng nổ' tốt đẹp về những gì đang xảy ra. – shellter

Các vấn đề liên quan