2012-01-22 3 views
23

Почему заявление if завершается успешно?

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

Если ваш запуск 'ps aux | grep "bla bla" 'вы увидите, почему ... –

+0

См. также [этот вопрос] (http://stackoverflow.com/questions/8965887/command-substitution-in-if-statement-condition). –

+3

'if pgrep -f" bla bla "; затем эхо «найдено»; fi' – jordanm

ответ

32

Поскольку сам grep процесс возвращается на ps. Вы можете «трюк» grep не совпадают себя окружающими один из символов для поиска в символьный класс [ ], который не меняет функциональность: Вобще:

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

Кроме того, использование процесса замещения $() является ненужным. if будет работать над успехом последней команды в цепочке трубопроводов, что вам и нужно.

Примечание: Причина классового характера трюк работает, потому что ps выход все еще имеет скобки класса символов, но когда grep обрабатывает строку поиска, она использует скобки как синтаксис, а не фиксированная строку, чтобы соответствовать.

+0

go go gadget downvoter – SiegeX

+0

Существует серийный downvoter там ..: P –

+0

Приятный трюк! Благодаря! –

7

Процесс «grep» уже запущен временем выполнения ps, поэтому выход ps включает его.

Попробуйте вместо этого использовать pgrep.

pgrep именно для этой цели:

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

+0

Mr Downvoter, я отредактировал свой ответ для большей ясности. Посмотрите, выглядит ли это сейчас. Ta – laher

1

Вам необходимо отфильтровать процесс, который grep пинг для «бла-бла»:

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

не хотите -v grep после целевого grep? (Если я опустил голову, я говорю, почему). – shellter

+0

Я также получил двойное голосование без объяснения причин. Я думаю, что кто-то очень либерализует по этому вопросу ... – laher

+0

@ amir75: похоже, что все нисходящие потоки исчезли (опять же без объяснения!) ;-) Удачи всем. – shellter

8

Если вы Grep вывод ps aux, вы всегда получите процесс, показывающий вашу предыдущую команду. Чтобы исправить это, вы можете дважды вывести вывод в grep, один раз, чтобы удалить строку с «grep» в нем, и снова для процесса, который вы ищете.

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

The $( небольших немного актуальный, и меняет смысл немного. Хотя в этом случае, поскольку из grep -q нет выхода, вы можете просто уйти с $(. Вы, вероятно, хотите, чтобы начать что-то вроде (как указывалось другими):

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

Во всяком случае, вы начали с

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

С $(, команда внутри $() выполняется и вывод, что команда используется в качестве командной строки для внешней команды.У этих четырех экспериментов:

# 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 

Таким образом, в соответствии с этим вы будете выход получить found, если оба эти условия:

  • Команда внутри $() не создал никакого вывода
  • и команда был достигнут

Это означает, что ps aux | grep -q "bla bla" был успешным и не создал выход. Неудивительно, что grep -q не создает выход. Для этого нужен -q. Поэтому ваша команда должна иметь истинный статус, что означает, что grep успешно нашел совпадение. Мы знаем, что grep всегда найдет совпадение в этом случае, потому что список процессов от ps будет включать в себя grep; grep всегда найдет себя.

+0

хорошее «взорванное» объяснение того, что происходит. – shellter

Смежные вопросы