В моем сценарии я пытаюсь проверить на наличие ошибок, равен ли первый и единственный аргумент -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]"
;$-
показывает активные флаги опций оболочки, а не имя текущего скрипта.$-
это не имя текущего скрипта.$0
является.Ответы:
Котировки!
if [ "$1" != -v ]; then
В противном случае, когда
$1
он полностью пустой, ваш тест станет:вместо того
[ "" != -v ]
... и
!=
не является унарным оператором (то есть может принимать только один аргумент).источник
if [[ $1 != -v ]]; then
IFS=1
, то[ $# -eq 1 ]
не будет вести себя так хорошо, хотя и тогда[ "$#" -eq 1 ]
ведет себя так, как задумано. Конечно, это патологический случай, но лучше писать программы, в которых их нет, когда есть выбор.Или то, что кажется безудержным излишеством, но на самом деле упрощенно ... Практически охватывает все ваши случаи, и никаких пустых строк или унарных проблем.
В случае, если первым аргументом является '-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
Но разрешить несколько вхождений аргумента удобно использовать в таких ситуациях, как:
Мы не заботимся о порядке аргументов и даже допускаем несколько аргументов -u. Да, просто разрешить:
источник
$*
не следует использовать в этом контексте: он объединяет элементы в строку, которая является как строковой, так и расширенной; отличие"$@"
, которое оставляет элементы с их точными исходными значениями. И вам не хватает некоторых цитат, которые улавливает shellcheck.net (с предупреждениями, связанными с вики-страницей, которая описывает, почему эти цитаты были важны).-U'Bob Barker'
:for arg in $*
увидит его как,-UBob
а затемBarker
как отдельный элемент; тогда какfor item in "$@"
будет выглядеть-UBob Barker
как одна строка.