- How to do an if statement from the result of an executed command
- 6 Answers 6
- You must log in to answer this question.
- Linked
- Related
- Hot Network Questions
- Subscribe to RSS
- If в Bash: от новичка до профессионала
- Основы
- Что происходит на самом деле
- Как насчет двойных квадратных скобок?
- А двойные круглые скобки?
- Использование команд вместо скобок
- Использование ваших собственных функций
- If – это хорошая вещь
How to do an if statement from the result of an executed command
I am trying to do an IF statement from the output of an executed commmand. Here is how I am trying to do it, but it doesn’t work. Does anyone know the right way to do this?
if [ "`netstat -lnp | grep ':8080'`" == *java* ]; then echo "Found a Tomcat!" fi
Regarding your recent edit: You are capturing the exit code, of the [ utility. The currently accepted answer captures the exit code of [[ , and the other answer captures the exit code of the grep -q pipeline.
6 Answers 6
Use the bash [[ conditional construct and prefer the $( ) command substitution convention. Additionally, [[ prevents word splitting of variable values therefore there is no need to quote the command substitution bit..
if [[ $(netstat -lnp | grep ':8080') == *java* ]]; then echo "Found a Tomcat!" fi
Another alternative is to simply test the exit status of grep itself, which will return false (non-zero) if there was no match and true (zero) if there was one, by not using the [ command.
if netstat -lntp | grep -q ':8080.*java'; then echo "Found a Tomcat!" fi
netstat -lntp | grep ':8080.*java' > /dev/null && command
If you just want to do one thing.
You can do more precise, yet simple, matching with awk.
if netstat -lnp | awk '$4 ~ /:8080$/ && $7 ~ /java/ END '; then …
To match the structure of your command more closely, the portable way of doing wildcard matching on a string in a shell is with the case construct.
case "$(netstat -lnp | grep ':8080')" in *java*) echo "Found a Tomcat!";; esac
Here’s how I did it in a script that determines whether my music player is open or not, and if a song is playing if it is open.
rbstatus=$(rhythmbox-client --print-playing) pgrep -x rhythmbox >/dev/null && if [ "$rbstatus" = "-" ]; then echo "No music playing" else rhythmbox-client --print-playing fi || echo "Music player is Closed."
Welcome on U&L! A side note: consider that && / || is not equivalent to if / else . Your code will print «Music player is Closed.» even if pgrep succeeds and the command in the else block fails (returns a non-zero status) for some reason (likely not a real issue in your case, of course).
netcat -zw3 localhost 8000 && echo 'tomcat is up'
You must log in to answer this question.
Linked
Related
Hot Network Questions
Subscribe to RSS
To subscribe to this RSS feed, copy and paste this URL into your RSS reader.
Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.7.14.43533
Linux is a registered trademark of Linus Torvalds. UNIX is a registered trademark of The Open Group.
This site is not affiliated with Linus Torvalds or The Open Group in any way.
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.
If в Bash: от новичка до профессионала
Перевод статьи «Bash If Statements: Beginner to Advanced».
Bash это интересный язык. Изначально он был создан для интерактивного использования в командной строке, главным образом в REPL (Read-Evaluate-Print-Loop – «цикл чтение-вычисление-вывод») для работы над одной командой пользователя за раз.
Этот язык спроектирован для существенной, но при этом лаконичной обработки простого текста. У этого есть побочный эффект: немного сложнее выполнять вещи, которые не являются интерактивными или связанными с текстом, например, арифметические вычисления, контроль потоков и манипуляции переменными.
В этой статье мы рассмотрим одну из немного запутанных тем: if-предложения. Мы погрузимся в их работу и узнаем, как более точно использовать ее механизмы.
Примечание: эта статья о Bash, однако большая часть всего сказанного здесь применима к Zsh и другим оболочкам. Некоторые из вещей несовместимы с POSIX.
Основы
If-предложения в Bash очень похожи на аналогичные в других языках. Они следуют базовой форме:
if [[ "$some_variable" == "good input" ]]; then echo "You got the right input." elif [[ "$some_variable" == "ok input" ]]; then echo "Close enough" else echo "No way Jose." fi
Дополнительный синтаксис в виде слова then , а также слегка странное закрывающее ключевое слово fi придает предложению немного экзотический вид, но в основе все то же самое, что и в других языках:
Если (if) что-то является истиной, тогда (then) выполни вот это. В противном случае проверяй другие условия по порядку и делай то же самое. Если ни одно из условий не сработало, выполни последнее указание.
Вы можете отбросить одну или все ветки elif , а также ветку else , если в них нет нужды!
Булевы операторы ! (нет), && (и), || (или) могут использоваться для комбинирования выражений, как и в других языках.
if [[ "$name" == "Ryan" ]] && ! [[ "$time" -lt 2000 ]]; then echo "Sleeping" elif [[ "$day" == "New Year's Eve" ]] || [[ "$coffee_intake" -gt 9000 ]]; then echo "Maybe awake" else echo "Probably sleeping" fi
Но здесь есть нечто запутанное. Порой вам встретятся двойные квадратные скобки, как в примере выше. А порой они будут одинарными.
if [ "$age" -gt 30 ]; then echo "What an oldy." fi
Иногда могут быть и круглыми!
if (( age > 30 )); then echo "Hey, 30 is the new 20, right?" fi
И временами их вообще не будет!
if is_upper "$1"; then echo "Stop shouting at me." fi
Как знать, какие именно скобки нужно использовать? Когда каждый из вариантов является подходящим? Почему какие-то из них не будут работать в определенных случаях?
Что происходит на самом деле
Есть магические слова, которые стоят за работой if в Bash: коды выхода. Вот шаблон того, что происходит на самом деле:
if ANY_COMMAND_YOU_WANT_AT_ALL; then # . stuff to do fi
Все верно: содержимое сразу после if может быть вообще любой командой, если она дает код выхода (а практически всегда так и бывает). Если команда возвращает код выхода 0 (в Bash это код успешно выполненной операции), тогда запускается код внутри ветки then . В противном случае Bash переходит к следующей ветке и делает новую попытку.
Но, погодите, это означает, что…
Ага. «[» это команда. Это, собственно, синтаксический сахар для встроенной команды test , которая проверяет и сравнивает переданные ей аргументы. «]» это на самом деле аргумент для команды [ , который говорит ей прекратить проверять аргументы!
if [ "$price" -lt 10 ]; then echo "What a deal!" fi
В этом примере команда [ принимает в качестве аргументов «$price» (переменная сразу же заменяется ее значением), -lt , 10 и ] .
Теперь, с учетом того что -lt , -gt и похожие числовые сравнения на самом деле являются аргументами, не кажется ли странный синтаксис немного более осмысленным? Они выглядят, как опции! Вот почему знаки > и < странно себя ведут внутри одинарных квадратных скобок: Bash думает, что вы пытаетесь перенаправить input или output внутри команды!
Как насчет двойных квадратных скобок?
Довольно странно, однако [[ двойные квадратные скобки ]] и (( двойные круглые скобки )) это не совсем команды. Они представляют собой ключевые слова языка Bash, в результате чего они ведут себя немного более предсказуемо. Тем не менее, в зависимости от своего содержимого, они по-прежнему возвращают код выхода.
[[ Двойные квадратные скобки ]] работают в целом так же, как и [ одинарные квадратные скобки ] , но имеют дополнительные возможности вроде лучшей поддержки регулярных выражений.
А двойные круглые скобки?
(( Двойные круглые скобки )) это конструкция, позволяющая осуществлять арифметические вычисления внутри Bash. Вам даже не нужно использовать их с if-предложением. Я часто ими пользуюсь, чтобы быстро инкрементировать счетчики и обновлять числовые переменные.
count=0 (( count++ )) echo "$count" # => 1 (( count += 4 )) echo "$count" # => 5
Чего вы не видите, это того, что круглые скобки тоже при каждом запуске возвращают код выхода. Если результат в скобках равен нулю, возвращается код выхода 1 (по сути, нулевой результат это «ложь»). Любой другой результат считается истиной, при нем код выхода будет 0. Вот пример:
if (( -57 + 30 + 27 )); then echo "First one" elif (( 2 + 2 )); then echo "Second one" else echo "Third one" fi # => "Second one"
К счастью для нас, знаки «больше» и «меньше» внутри круглых скобок работают прекрасно. Если сравнение истинно, результат будет 1. В противном случае – 0.
if (( 5 > 3 )); then echo "Numbers make sense." elif (( 3 "Numbers make sense"
У этой функциональности есть странный, но любопытный побочный эффект:
echo $(( (5 > 3) + (0 == 0) )) # => 2 # Each comparison is true, so we're effectively echoing # 1 + 1. Fun, right?
Использование команд вместо скобок
Чаще всего в ваших if-предложениях будут использоваться скобки. Однако, поскольку можно использовать команды и их коды выхода, за вашими if-ами будет стоять вся мощь командной строки.
Скажем, мы хотим сделать что-то, но только в том случае, если в файле найдена определенная строка. Какую команду вы будете использовать для поиска текста в файлах? Grep!
echo "Hello, welcome to bean house." >> dialogue.txt echo "Would you like some coffee?" >> dialogue.txt if grep -q coffee dialogue.txt; then echo "Found coffee, boss." else echo "No coffee." fi # => "Found coffee, boss."
Если grep находит искомое, код выхода будет 0 (успех). Если нет, – 1. Мы используем это для запуска нашего if-предложения! Опция -q в grep означает —quiet . Она запрещает вывод найденных строк. Если мы ее уберем, то наш вывод будет выглядеть так:
Would you like some coffee? Found coffee, boss.
Использование ваших собственных функций
Самое лучшее в этом всем то, что вы можете написать собственные функции! Это поможет вам инкапсулировать вашу логику в нечто с высокоуровневым именем. Благодаря этому ваши скрипты станут более читаемыми, а ваши намерения – более понятными. И если есть что-то, где мы можем для примера использовать эту дополнительную ясность, это «выбрасывающий» скрипт, который Джерри написал в прошлом году и который мы до сих пор используем в сборочном конвейере.
Мне стоит написать отдельный пост о функциях в Bash, потому что они прекрасны и я их обожаю. А сейчас лишь отмечу, что эти функции работают как маленькие отдельные скрипты. Любые переданные им аргументы могут назначаться позиционно с помощью особых переменных $1 , $2 , $3 и т. д. Число аргументов содержится в переменной $# .
Обратите внимание на использование return вместо exit. Смысл тот же самый, за исключением того, что exit «убивает» весь скрипт, а не просто завершает функцию. Данная функция может использоваться вот так:
function is_number < if [[ "$1" =~ ^[[:digit:]]+$ ]]; then return 0 else return 1 fi >age="$1" if ! is_number "$age"; then echo "Usage: dog_age NUMBER" exit 1 fi
Видите, как намерение программиста и логика становятся яснее без реализации деталей и написания громоздких регулярных выражений? Функции в Bash это Хорошо.
Фактически, если функция не возвращает (return) значение недвусмысленно, это возвращаемое значение последней команды в функции используется неявно, поэтому функцию можно сократить:
Если регулярное выражение сработает, код возврата двойных квадратных скобок будет нулевым, и таким образом функция возвращает 0. Если нет, и то, и другое возвращает 1. Это отличный способ давать имена регулярным выражениям.
If – это хорошая вещь
Вот и все! Применяйте полученные знания для чистки своих скриптов. Если у вас есть примеры использования if-предложений в Bash, которые могут быть полезны и другим людям, – поделитесь в комментариях!