Умовні позначення Баша: як вирази "та"? (якщо [! -z $ VAR && -e $ VAR])


281

Я думаю, мені не зрозуміло, як робити "і" тести. Я хотів переконатися, що існував аргумент, з яким добре працювали [ -e $VAR ], але виявляється, що він також оцінював як істинне на порожній рядку; чого я не хочу.

Як я 'і' їх разом? Або є ще одне одинарне випробування, яке виконує те, що я хочу?

Відповіді:


532
if [ ! -z "$var" ] && [ -e "$var" ]; then
      # something ...
fi

9
Це рішення працює навіть у суворо сумісних з POSIX оболонках, а отже, і в bash; проте, щоб повною мірою скористатися "башизмами", див. відповідь @ paxdiablo.
mklement0

2
Дуже радий бачити це радити замість застарілого -a.
Чарльз Даффі

1
Я знайшов ще один відмінний і детальне пояснення - stackoverflow.com/questions/3601515 / ...
valentt

70

З сторінки сторінки bash:

[[ expression ]] - повернути статус 0 або 1 залежно від оцінки виразу умовного виразу.

І для виразів одним із варіантів є:

expression1 && expression2- вірно, якщо і те, expression1і інше expression2.

Таким чином, ви можете зробити andїх разом наступним чином ( -nце навпаки, -zщоб ми могли позбутися !):

if [[ -n "$var" && -e "$var" ]] ; then
    echo "'$var' is non-empty and the file exists"
fi

Однак я не думаю, що це потрібно в цьому випадку, -e xyzzyце правда, якщо xyzzy файл існує і може досить легко обробляти порожні рядки. Якщо це те, що ви хочете, тоді вам фактично не потрібен -zне порожній чек:

pax> VAR=xyzzy
pax> if [[ -e $VAR ]] ; then echo yes ; fi
pax> VAR=/tmp
pax> if [[ -e $VAR ]] ; then echo yes ; fi
yes

Іншими словами, просто використовуйте:

if [[ -e "$var" ]] ; then
    echo "'$var' exists"
fi

1
Ми можемо скоротити його[[ -e "$var" ]] && echo "'$var' exists"
jaypal singh

1
Так, якщо це однолінійний (як у мене був приклад). Я б цього не зробив, якби умовний блок був набагато складнішим.
paxdiablo

в разі , якщо є тільки один - може бути , навіть давно одна - команда, то має сенс використовувати цю форму , як вона коротше
AVP

9
if [ -n "$var" -a -e "$var" ]; then
    do something ...
fi

 


10
Так як POSIXне визначає поведінку [складних наборів тестів, ми повинні уникати використання -aабо -oз [. Я читав це тут .
jaypal singh

2
@ jaypal-singh Ви маєте рацію, але в темі є bashтег і не згадується про POSIX, тому я публікую цю версію, яка працює під bashта деякими іншими сучасними оболонками.
Слава Семушин

2
Якщо ви припускаєте використання bashабо інших сучасних снарядів, є ще менше підстав рекомендувати -a.
чепнер

Навіть з bash, спосіб поведінки цих тестів не є чітко визначеним у всіх кутових випадках. Розгляньте [ "$var1" -o "$var2" ]; якщо var1=(і var2=), то те, що ми маємо, є тестом на те, чи -oє не порожнім, а не тим, var1чи var2є не порожнім. Цей різновид двозначності є єдиною законною причиною x$varідіоми в сучасних (тобто, після 90-х) testкомандах з правильним цитуванням, і цю ідіому потрібно загинути у пожежі.
Чарльз Даффі

4

Просто цитуйте свою змінну:

[ -e "$VAR" ]

Це визначається, [ -e "" ]якщо $VARпорожній.

Ваша версія не працює, тому що вона оцінює [ -e ]. Тепер у цьому випадку bash просто перевіряє, чи єдиний аргумент ( -e) є не порожнім рядком.

З сторінки сторінки:

тестуйте та [оцінюйте умовні вирази, використовуючи набір правил на основі кількості аргументів. ...

1 аргумент

Вираз є істинним, якщо і лише тоді, коли аргумент недійсний.

(Крім того, це рішення має додаткову перевагу роботи з назви файлів, що містять пробіли)


1

Зараз я знайшов відповідь. Дякуємо за ваші пропозиції!

for e in ./*.cutoff.txt; do
if grep -q -E 'COX1|Cu-oxidase' $e
then
    echo xyz >$e.match.txt
else
    echo
fi

if grep -q -E 'AMO' $e
then
    echo abc >$e.match.txt
else
    echo
fi; done

Будь-які коментарі до цього? Це здається неефективним, щоб двічі грепнути, але це працює ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.