як перевірити, чи недійсні $ 1 і $ 2?


40

Я запускаю якийсь сценарій, який передає аргумент рядка, і я хочу це зробити, якщо оператор else показаний, як показано нижче:

if [ $1 != '' ] && [ $2 != '' ]
then 
    do something.....

але це показано Error too many argument. Чому?


Ви повинні надати 1. команду, яку ви викликаєте сценарій, і 2. повний вихід.
Лусіо

2
Ви повинні використовувати [[ ]]. Інакше вам доведеться цитувати свої змінні.
Крістоф Де Троєр

Якщо б $ 1 не існувало, то $ 2 перетворився б на 1 долар, що робить тест у розмірі 1 та 2 доларів недійсним здається безрезультатним.
WinEunuuchs2Unix

@ WinEunuuchs2Unix Не обов'язково не має значення - у деяких випадках ви хочете переконатися, що насправді щось є замість порожнього чи нульового рядка в аргументах. $1може бути скасовано або встановлено нульовий рядок користувачем сценарію. Розглянемо цю послідовність команд: $ set '' barтоді встановлюються echo "x${1}x";обидві змінні, але одна з них є нульовою.
Сергій Колодяжний

Відповіді:


55

Спробуйте скористатися тестом -z:

if [ -z "$1" ] && [ -z "$2" ]

Від людини bash:

-z string
   True if the length of string is zero.

Це працює для мене!
pengisgood

Цікаво , що найбільше кількість голосів і загальноприйнятий відповідь не на самому ділі відповісти на поставлене питання.
mehmet

Під час написання портативних скриптів оболонки цей прапор слід використовувати обережно, оскільки на певних комерційних Unixes цей прапор є несправним. Дивіться мою відповідь щодо пов’язаних джерел.
Сергій Колодяжний


3

Наступне також працює,

if [ "$1" == "" && "$2" == ""]; then
    echo NULL
fi

&&І інші логічні команди роздільники не допускаються в класичний test. Ви повинні використовувати інші тестові конструкції (наприклад -a, я думаю)
muru

3

Стару версію відповіді див. У другій частині цієї відповіді. Якщо ви хочете дізнатися про деталі, читайте далі

Причина випуску

У самому питанні повідомляється, що ОП бачить too many arguments error, що при тестуванні bashне здається:

$ [ $1 != '' ] && [ $2 != '' ]
bash: [: !=: unary operator expected

З /bin/shякою фактично посилається /bin/dashна Ubuntu, про помилку повідомляється наступним чином:

$ sh
$ [ $1 != '' ] && [ $2 != '' ]
sh: 1: [: !=: unexpected operator

І окремий /bin/testтакож:

$ /usr/bin/test $1 != ''  
/usr/bin/test: missing argument after ‘’

Sidenote: Якщо вам цікаво , що /usr/bin/testі чому я використовую bashі sh, то ви повинні знати , що [це псевдонім для testкоманди, яка також існує як окремий виконуваний файл або частіше - в якості оболонки вбудованої в якій то , що кожна оболонка буде використовувати перший . Що стосується ifвисловлювань, вони працюють на статусах виходу команд, отже, чому [і testє командами, причому все інше є аргументами для цих команд - неправильний порядок цих аргументів командного рядка призводить до помилок.

Повернутися до теми: незрозуміло, як ОП отримала непов’язану помилку. Однак у всіх 3 випадках проблема однакова - незмінна змінна буде розглядатися як порожня, тому те, що оболонка бачить із цими цитованими змінними, є

[ != '' ]

який розбиває синтаксис, який testрозуміє. Пам'ятаєте, що я сказав про неправильний порядок аргументів командного рядка? Отже, чому цитування важливе. Увімкніть діагностичний вихід і подивимося, що виконується оболонка:

$ set -x
# throws error
$ [ $1 != '' ] && [ $2 != '' ] 
+ '[' '!=' '' ']'
bash: [: !=: unary operator expected
# no error
$ [ "$1" != '' ] && [ "$2" != '' ] || echo null vars
+ '[' '' '!=' '' ']'
+ echo null vars
null vars

Кращий спосіб перевірити невстановлені змінні

Дуже частий підхід, який ви бачите навколо:

 if [ "x$var1" == "x"  ] && [ "x$var2" == "x"  ];                                                                
 then
     echo "both variables are null"
 fi

Щоб цитувати Жиля :

У ["x $ 1" = "x"] префікс x гарантує, що x "$ 1" не може бути схожим на оператора, тому єдиним способом оболонка може проаналізувати цей тест, трактуючи = як двійковий оператор.

Імовірно, це має бути досить портативно, оскільки я бачив це у /bin/shсценаріях. Він також може поєднуватися як в

if [ "x${var1}${var2}" == "x" ]; then
    ...
fi

Звичайно, ми можемо використовувати -zпрапор, однак згідно з дослідженнями в деяких снарядах, зокрема ksh88 (за словами Стефана Шазеласа ), цей прапор є несправним.

Дивитися також


+1 за дуже цікавий підхід.
WinEunuuchs2Unix

@ WinEunuuchs2Unix Відредаговано, щоб зробити його ще цікавішим :)
Сергій Колодяжний

1

Я думаю, що назва публікації не є точною, оскільки намір у повідомленні полягав у тому, щоб перевірити, чи не є 1 і 2 долари недійсними. У наведеному прикладі просто не вистачало подвійних котирувань у $ 1 та $ 2 для роботи. Змінні повинні бути подвійними цитатами, щоб їх розширити при порівнянні рядків. Але перевірити, чи існують $ 1 і $ 2, це те саме, що перевірити, чи існують $ 2, так як він не може існувати, якщо немає $ 1. Команда "якщо" також не потрібна в цьому випадку, оскільки "test" повертає true / false та використовує "&&" як "then", якщо return 0 / true:

[ "$2" != '' ] && commands...

Простіше, з -n (ненульовий):

[ -n "$2" ] && commands...

"Перевірити, чи недійсні $ 1 і $ 2" було б те саме, що перевірити, якщо немає параметра:

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