Помилка сценарію Bash [:! =: Очікується одинарний оператор


96

У моєму сценарії я намагаюся перевірити помилку, якщо перший і єдиний аргумент дорівнює -v, але це необов’язковий аргумент. Я використовую оператор if, але постійно отримую очікувану помилку унарного оператора.

це код:

if [ $1 != -v ]; then
   echo "usage: $0 [-v]"
   exit
fi

Редагувати:

Я повинен бути більш конкретним: Ця частина сценарію вище перевіряє необов’язковий аргумент, а потім, якщо аргумент не введено, він повинен запустити решту програми.

#!/bin/bash

if [ "$#" -gt "1" ]; then
   echo "usage: $0 [-v]"
   exit
fi

if [ "$1" != -v ]; then
   echo "usage: $0 [-v]"
   exit
fi

if [ "$1" = -v ]; then
   echo "`ps -ef | grep -v '\['`"
else
   echo "`ps -ef | grep '\[' | grep root`"
fi

... до речі, я думаю, ти хочеш echo "usage: $0 [-v]"; $-показує активні параметри оболонки, а не ім'я поточного сценарію.
Чарльз Даффі

Я маю цю частину правильно, я хочу, щоб вона відображала назву поточного сценарію.
user3380240

4
Ласкаво просимо до stackoverflow, і зокрема до тегу bash! Перегляньте вікі-теги на корисні інструменти та ресурси, такі як перевірка оболонки, яка вкаже (хоча і не завжди пояснює) багато подібних проблем.
той інший хлопець

@ user3380240, $-це не ім'я поточного сценарію. $0є.
Чарльз Даффі

Вибачте, це була помилка.
user3380240

Відповіді:


189

Цитати!

if [ "$1" != -v ]; then

В іншому випадку, коли $1він повністю порожній, ваш тест стає:

[ != -v ]

замість

[ "" != -v ]

... і !=не є одинарним оператором (тобто таким, який може взяти лише один аргумент).


8
Або, якщо вас не турбує портативність, ви можете використовувати подвійні дужки, всередині яких не потрібно цитувати змінні розширення: if [[ $1 != -v ]]; then
Майк Холт

@MikeHolt, справді - я це викладаю у коментарі до вищезазначеного питання.
Чарльз Даффі

@DanielDinnyes, якщо IFS=1, тоді [ $# -eq 1 ]не буде поводитися так добре, тоді як [ "$#" -eq 1 ]поводиться як задумано навіть тоді. Звичайно, це патологічний випадок, але краще писати програмне забезпечення, яке їх не має, коли їм надають вибір.
Чарльз Даффі

-2

Або для того, що здається нестримним надмірним, але насправді спрощеним ... Майже охоплює всі ваші справи, і немає порожніх рядків чи одинарних проблем.

У випадку, якщо першим аргументом є '-v', тоді зробіть умовний ps -ef, інакше у всіх інших випадках киньте використання.

#!/bin/sh
case $1 in
  '-v') if [ "$1" = -v ]; then
         echo "`ps -ef | grep -v '\['`"
        else
         echo "`ps -ef | grep '\[' | grep root`"
        fi;;
     *) echo "usage: $0 [-v]"
        exit 1;; #It is good practice to throw a code, hence allowing $? check
esac

Якщо когось не цікавить, де знаходиться аргумент '-v', то просто опустіть справу у цикл. Це дозволить ходити всі аргументи і знаходити '-v' де завгодно (за умови, що воно існує). Це означає, що порядок аргументів командного рядка не важливий. Зверніть увагу, як представлено, змінна arg_match встановлена, отже, це лише прапор. Це дозволяє багаторазово повторювати аргумент '-v'. Можна проігнорувати всі інші випадки появи '-v' досить легко.

#!/bin/sh

usage ()
 {
  echo "usage: $0 [-v]"
  exit 1
 }

unset arg_match

for arg in $*
 do
  case $arg in
    '-v') if [ "$arg" = -v ]; then
           echo "`ps -ef | grep -v '\['`"
          else
           echo "`ps -ef | grep '\[' | grep root`"
          fi
          arg_match=1;; # this is set, but could increment.
       *) ;;
  esac
done

if [ ! $arg_match ]
 then
  usage
fi

Але дозволити багаторазове входження аргументу зручно використовувати в таких ситуаціях, як:

$ adduser -u:sam -s -f -u:bob -trace -verbose

Ми не дбаємо про порядок аргументів і навіть допускаємо множинні аргументи -u. Так, це також проста справа, щоб також дозволити:

$ adduser -u sam -s -f -u bob -trace -verbose

$*не слід використовувати в цьому контексті: він об'єднує елементи у рядок, який є як розділеним, так і розширеним за допомогою глобуса; на відміну від "$@", що залишає предмети з їх точними вихідними значеннями. І вам не вистачає деяких цитат, які shellcheck.net схопить (із застереженнями, пов’язаними зі сторінкою wiki, яка описує, чому ці цитати були важливими).
Чарльз Даффі

Розглянемо як конкретний приклад -U'Bob Barker': for arg in $*буде бачити це як, -UBobа потім Barkerяк окремий елемент; тоді як for item in "$@"буде розглядатися -UBob Barkerяк один рядок.
Чарльз Даффі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.