2012-01-22 15 views
23

Dlaczego następujące oświadczenie if kończy się powodzeniem?

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

Jeśli prowadzisz 'ps aux | grep "bla bla" 'zobaczysz, dlaczego ... –

+0

Zobacz także [to pytanie] (http://stackoverflow.com/questions/8965887/command-substitution-in-if-statement-countition). –

+3

'if pgrep -f" bla bla "; następnie echo "znalezione"; fi' – jordanm

Odpowiedz

32

Ponieważ sam proces grep jest zwracany przez ps. Można „trick” grep nie zgadza się przez otaczający jeden z bohaterów wyszukiwania w klasie znaków [ ] który nie zmienia funkcjonalność: Wystarczy zrobić:

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

Również zastosowanie substytucji procesowej $() jest niepotrzebne. if będzie działać na sukces ostatniego polecenia w łańcuchu rur, który jest tym, czego potrzebujesz.

Uwaga: Powodem trick klasa znaków działa dlatego, że wyjście ps wciąż ma wsporniki klasa znaków, ale gdy grep przetwarza ciąg wyszukiwania, używa wsporniki jak składni zamiast stałej łańcucha, aby dopasować.

+0

Idź gadżet gadżetu – SiegeX

+0

Jest tam szeregowy downvoter ..: P –

+0

Dobra sztuczka! Dzięki! –

7

Proces "grep" jest już uruchomiony przed uruchomieniem ps, więc wyjście ps zawiera go.

Spróbuj użyć zamiast tego pgrep.

pgrep właśnie do tego celu:

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

+0

Panie Downvoter, zredagowałem moją odpowiedź dla większej przejrzystości. Sprawdź, czy teraz wygląda lepiej. Ta – laher

1

musisz odfiltrować proces, który jest grep ping dla 'bla bla':

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

nie chcesz uzyskać -v grep po grepie docelowym? (Jeśli zgodzę się, powiem dlaczego). – shellter

+0

Zajęto mnie również dwukrotnie bez żadnego wyjaśnienia. Myślę, że ktoś bardzo liberalnie podchodzi do tego pytania ... – laher

+0

@ amir75: Wygląda na to, że wszystkie downvotes zniknęły (znowu bez wyjaśnienia!) ;-) Powodzenia wszystkim. – shellter

8

Jeśli grep wyjście z ps aux, zawsze otrzymasz proces pokazujący poprzednie polecenie. Aby to naprawić, możesz wyprowadzić wyjście do grep dwukrotnie, raz, aby usunąć linię z "grep" w niej, i ponownie dla procesu, którego szukasz.

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

The $( jest mały trochę znaczenie i zmienia znaczenie trochę. Chociaż w tym przypadku, ponieważ nigdy nie ma żadnego wyjścia z grep -q, możesz uciec z $(. Prawdopodobnie chcesz, aby zacząć od czegoś podobnego (jak wskazano przez innych):

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

W każdym razie, na początek z

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

Z $( polecenie wewnątrz $() jest wykonywany, a wyjście z tego polecenie jest używane jako linia poleceń dla polecenia zewnętrznego.Czy te cztery eksperymenty:

# 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 

Więc zgodnie z tym będzie wyjście dostać found jeśli oba te warunki przytrzymanie:

  • Polecenie wewnątrz $() stworzył żadnego wyjścia
  • i polecenie był skuteczny

Sugeruje to, że ps aux | grep -q "bla bla" zakończyło się pomyślnie i nie utworzono żadnego wyjścia. Nic dziwnego, że grep -q nie generuje żadnych danych wyjściowych. Właśnie do tego służy -q. Tak więc twoje polecenie musi mieć prawdziwy status, co oznacza, że ​​grep z powodzeniem znalazł dopasowanie. Wiemy, że grep zawsze znajdzie dopasowanie w tym przypadku, ponieważ lista procesów od ps będzie zawierała samą grep; grep zawsze się odnajdzie.

+0

ładne "eksplodowane" wyjaśnienie tego, co się dzieje. – shellter

Powiązane problemy