У bash-скрипті, використовуючи умовний оператор "або" в "якщо"


127

Це питання є продовженням свого роду попереднє запитання . Користувачі на цьому сайті люб’язно допомогли мені визначити, як написати forцикл bash, який повторюється над значеннями рядка. Наприклад, припустимо, що змінна керування циклом перетворюється fnameна рядки "a.txt" "b.txt" "c.txt". Я хотів би echo"так!" коли fnameмає значення "a.txt"або "c.txt", і echo"ні!" інакше. Я спробував такий сценарій bash shell:

#!/bin/bash

for fname in "a.txt" "b.txt" "c.txt"
do
 echo $fname
 if [ "$fname" = "a.txt" ] | [ "$fname" = "c.txt" ]; then
 echo "yes!"
else
 echo "no!"
fi
done

Я отримую вихід:

a.txt

немає!

b.txt

немає!

c.txt

так!

Чому ifтвердження, мабуть, відповідає дійсності, коли fnameмає значення "a.txt"? Я |неправильно користувався?


3
У bash, 'або' оператор є '||' (C стиль).
Маріус Котофана

3
Ви також можете використовувати -oв межах одного [ ].
Тор

6
@Тор я вважаю за краще ||і розділити [ ]їх -oна портативність просто тому [, що не гарантовано підтримувати більше 4 аргументів. Звичайно , якщо мову перекладу bash, ніхто не повинен використовувати в [будь-якому випадку , тому що bash«s [[перевершує у багатьох відношеннях.
jw013

2
@ jw013 Дякую Чи означає це, що я повинен використовувати, if [[ "$fname" = "a.txt" ]] || [[ "$fname" = "c.txt" ]]а не if [ "$fname" = "a.txt" ] || [ "$fname" = "c.txt" ]?
Андрій

5
@Andrew Це правильно, якщо, як ти оголошуєш шебанг як bash, як ти вже робиш. Однією з переваг [[є те, що він не робить розділення слів (особливий випадок), тому [[ $unquoted_var = string ]]це безпечно.
jw013

Відповіді:


225

Якщо ви хочете сказати, ORвикористовуйте подвійну трубу ( ||).

if [ "$fname" = "a.txt" ] || [ "$fname" = "c.txt" ]

(Оригінальний код OP, який використовується, |був просто підведенням виводу лівої сторони до правої сторони так само, як працює будь-яка звичайна труба.)


4
Крім того, ||не виконує стандартну логіку "АБО" - це коротке замикання, а друга команда виконується лише в тому випадку, коли перша виходить з ладу.
holdenweb

13
@holdenweb Я впевнений, що більшість сучасних оптимізованих мов працюють однаково. Не потрібно витрачати цикли процесора на оцінку другої умови, ORякщо перша умова оцінює істину.
Багамат

1
Я подумав, що Башу сподобався, ==але побачивши цю відповідь, я вирішив подивитися на це. Мабуть, "це можна використовувати, але не є стандартним". Я думав , що я б поставив це тут для інших , якщо ваш цікавий: stackoverflow.com/a/2237103
harperville

Ось що testрекомендує і сторінка man
cdosborn

2
Ви також можете використовувати тести з подвійною дужкою - if [[ "$fname" = "a.txt" ]] || [[ "$fname" = "c.txt" ]](Якщо ви хочете або вам потрібно мати додаткову функціональність [[ ]]).
HankCa
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.