скрипт bash [x $ 1 = x]

21

Я читаю скрипт bash Я не понимаю, что там происходит.

#!/bin/sh
[ x$1 = x ] 

Что происходит на второй линии и что [ x$1 = x ] значит?

боб
источник

Ответы:

27

Это проверяет, что $1пусто, хотя оно должно быть заключено в кавычки (идентично [ -z "$1" ]). Некоторые очень старые оболочки не обрабатывали пустые строки должным образом, поэтому разработчики переносимых сценариев приняли этот стиль проверки. В течение десятилетий в этом не было необходимости, но люди все еще так делают, потому что люди все еще так делают.

Kevin
источник
Да, вы не должны делать это больше так и принять более современный стиль. Если вы не работаете на PDP11.
MacLemon
4
Это не так много о пустых строках. [ x$1 = x ]все еще неверно, но [ "x$1" = x ]будет для оболочек, у которых есть проблема, где $1есть !или (или -n.... [ "" = "$1" ]и case $1 in "")также будет в порядке, хотя.
Стефан Шазелас
2
@MacLemon, нет необходимости заходить так далеко назад. [ -z "$1" ]и [ "$1" = "" ]до сих пор не работает с / bin / sh Solaris 10, первый с dash-0.5.4.
Стефан Шазелас
1
+1 за последнее предложение!
Гленн Джекман
1
@glennjackman, последнее предложение неверно. Solaris 10 по-прежнему является наиболее широко развернутой версией Solaris и [ "$1" = "" ]до сих пор не работает с ней /bin/sh(хотя вы бы хотели использовать ее /usr/xpg4/bin/shтам, а не /bin/sh). черта была исправлена ​​в этом отношении в январе 2009 года.
Стефан Шазелас
8

Квадратные скобки указывают на тест , поэтому [ x$1 = x]без ifили что-то подобное бессмысленно, хотя синтаксически нормально.

Он предназначен для оценки true, если x$1расширяется до x, и false в противном случае, но, поскольку он не заключен в кавычки, если $1(например) "hey x", оболочка увидит x = x, поэтому эта конструкция все еще небезопасна.

Цель x = xпроверки - определить, является ли переменная пустой. Более распространенный способ сделать это - просто использовать кавычки:

if [ "$1" = "" ]; then

Операторы тестирования Bash -zи -nтакже могут быть использованы, но они менее переносимые на другие типы оболочек. 1

Причина кавычек, или, в том x$1, что левая часть не расширяется ни к чему, что было бы синтаксической ошибкой:

if [  = x ]  # No good!
if [ "" =  "" ] # Okay.
if [ x = x ] # Also okay.

1. На самом деле testможет быть автономной утилитой, но большинство оболочек реализуют ее как встроенную; проверьте разницу между which testи type test. В GNU / Linux man testутверждается, что он ссылается на встроенный, но если вы вызываете (например) /usr/bin/test, эта утилита, кажется, реализует функции, описанные на странице руководства, включая -zи -n.

лютик золотистый
источник
1
[ x$1 = x ]также оценивается как истинное, если, $1например " -o x". Попробуй sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]неправильно и не имеет смысла.
Стефан Шазелас
@ StéphaneChazelas Спасибо SC - отредактировано (2-й абзац).
Златовласка
you don't need if to use test, you can use it before &&, || or after while or examine the result using $?
Jasen
8
[ x$1 = x ]

Имеет смысл только в zsh. Это сравнивает конкатенацию xс первым аргументом скрипта с x. Таким образом, [команда возвращает true, если $1она пуста или не указана.

[ $1 = "" ]

Не будет работать , потому что, в zshкогда пустая переменная не указаны в списке контекстов, он расширяется без аргумента вообще вместо пустого аргумента, так что, если $1было задано или пустой, то [команда получит только в качестве аргументов [, =пустая строка и из ]которого это не могло иметь смысла. [ -z "$1" ]или [ "$1" = "" ]было бы хорошо, хотя, как в оболочках POSIX.

В Bourne-подобных оболочках / POSIX, [ x$1 = x ]не имеет смысла. Это оператор split + glob, каким-то образом примененный к конкатенации xи первому аргументу скрипта, в надежде получить результат и =и x, и ]составить правильное тестовое выражение для [команды.

Например, если сценарий был передан один " = x -o x ="аргумент, [получат эти аргументы: [, x, =, x, -o, x, =, x, ], что [бы понять , как сравнение xс xи xс xи возвращает истину.

Если бы $1были "* *", то оболочка передала бы [команде список файлов в текущем каталоге, имя которого начинается с x(расширение glob x*), тогда список не скрытых файлов (расширение *) ... что [вряд ли сможет иметь какой-либо смысл из. Единственные случаи, когда это могло бы сделать что-нибудь разумное, это если $1они не содержат подстановочных знаков или пустых символов.

Теперь, что вы иногда находите, это код:

[ "x$1" = x ]

Это используется для проверки, если $1он пуст или не установлен.

Обычный способ проверить пустую или неустановленную переменную:

[ -z "$1" ]

Но это не работает для некоторых значений $1подобно =в некоторых (не POSIX) [реализациях, таких как встроенная в оболочку Bourne, как в /bin/shSolaris 10 и ранее, или в некоторых старых версиях dash(до 0.5.4) или shнекоторых BSD.

Это потому , что [видит [, -z, =, ]и жалуется на отсутствующие аргументы =бинарного оператора вместо понимания его как -zунарный оператор применяется к =строке.

Точно так же, [ "$1" = "" ]терпит неудачу для некоторых реализаций [if $1is !или (.

В этих оболочках / [реализациях:

[ "x$1" = x ]

всегда является действительным тестом независимо от значения $1, поэтому:

[ "" = "$1" ]

а также:

[ -z "${1:+x}" ]

а также

case $1 in "") ...; esac

Конечно, если вы хотите проверить, что аргумент не предоставлен, вы должны сделать:

[ "$#" -eq 0 ]

То есть вы проверяете количество аргументов, переданных скрипту.

Обратите внимание, что в настоящее время [ -z "$var" ]он четко определен POSIX и не может дать сбой в совместимых [реализациях (а bashэто [есть и было на протяжении десятилетий). Так что вы должны быть в состоянии положиться на него в POSIX sh или bashскриптах.

Стефан Шазелас
источник
0

x$1объединяет две строки xи, $1если $ 1 пусто, x $ 1 равно x, и в результате [x $ 1 = x] будет истинным. x = yиспользуется для сравнения строки в sh

harish.venkat
источник
2
Нет x$1не указано, поэтому для них выполняется разбиение и подстановка.
Стефан Шазелас
0

[ x$1 = x ]Истинно, если $1не установлено / пусто / пусто или нет.
Попробуйте себя с:
TEST= ;[ x$TEST = x] && echo "TEST is unset"
и
TEST=lolz ;[ x$TEST = x ] && echo "TEST is unset"

xx4h
источник
1
[ x$1 = x ]также верно, если, $1например " -o x". Попробуй sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]неправильно и не имеет смысла.
Стефан Шазелас