Как я могу протестировать, если переменная пуста или содержит только пробелы?

249
29.07.2014, 00:53
9 ответов

Во-первых, обратите внимание, что тест -z явно предназначен для:

длина строки равна нулю

То есть строка, содержащая только пробелы, не должна не будет истинным под -z , потому что он имеет ненулевую длину.

Вы хотите удалить пробелы из переменной с помощью расширения параметра замены шаблона :

[[ -z "${param// }" ]]

Это расширяет переменную param и заменяет все совпадения с шаблоном (одиночный пробел) без ничего, поэтому строка, содержащая только пробелы, будет расширена до пустой строки.


Суть в том, как это работает , заключается в том, что $ {var / pattern / string} заменяет первое самое длинное совпадение шаблона на строка . Когда шаблон начинается с / (как указано выше), он заменяет все совпадения. Поскольку замена пуста, мы можем опустить окончательное / и значение строки :

$ {параметр / шаблон / строка}

Шаблон ] расширяется для создания шаблона так же, как при расширении имени файла. Параметр раскрывается, и самое длинное совпадение шаблона с его значением заменяется строкой . Если шаблон начинается с «/», все совпадения с шаблоном заменяются строкой . Обычно заменяется только первое совпадение. ... Если строка равна нулю, совпадения с шаблоном удаляются, а / следующий шаблон может быть опущен.

После всего этого мы получаем $ {param //} для удаления всех пробелов.

Обратите внимание, что, хотя он присутствует в ksh (откуда он возник), zsh и bash , этот синтаксис не является POSIX и не должен использоваться в ] sh скрипты.

299
27.01.2020, 19:27

Для тестирования, если переменная пуста или содержит пробелы, можно также использовать этот код:

${name:?variable is empty}
1
27.01.2020, 19:27

Единственная оставшаяся причина для написания сценария оболочки вместо сценария на хорошем языке сценариев заключается в том, что чрезвычайная переносимость является первостепенной задачей. Устаревший / bin / sh - единственное, в чем вы можете быть уверены, но Perl, например, более , вероятно, будет доступен кроссплатформенным, чем Bash. Поэтому никогда не пишите сценарии оболочки, которые используют функции, которые не являются действительно универсальными - и имейте в виду, что некоторые поставщики проприетарных Unix заморозили среду оболочки до выхода POSIX.1-2001 .

Существует переносимый способ выполнить этот тест, но вы должны использовать tr :

[ "x`printf '%s' "$var" | tr -d "$IFS"`" = x ]

(Значение по умолчанию $ IFS , для удобства, представляет собой пробел, a вкладку и новую строку.)

(Встроенная команда printf сама по себе очень портативна, но полагаться на нее гораздо проще, чем выяснять, какой вариант echo у вас есть.)

5
27.01.2020, 19:27

Самый простой способ проверить, что строка содержит только символы из авторизованного набора, - это проверить наличие неавторизованных символов. Таким образом, вместо проверки того, содержит ли строка только пробелы, проверьте, содержит ли строка какой-либо символ, отличный от пробела. В bash, ksh или zsh:

if [[ $param = *[!\ ]* ]]; then
  echo "\$param contains characters other than space"
else
  echo "\$param consists of spaces only"
fi

«Состоит только из пробелов» включает случай пустой (или не установленной) переменной.

Вы можете проверить наличие любого символа пробела. Используйте [[$ param = * [^ [: space:]] *]] , чтобы использовать настройки локали или любой другой явный список пробельных символов, которые вы хотите проверить, например [[$ param = * [$ '\ t \ n'] *]] для проверки наличия пробела, табуляции или новой строки.

Сопоставление строки с шаблоном с = внутри [[…]] - это расширение ksh (также присутствует в bash и zsh). В любом стиле Bourne / POSIX вы можете использовать конструкцию case для сопоставления строки с шаблоном. Обратите внимание, что стандартные шаблоны оболочки используют ! , чтобы инвертировать набор символов, а не ^ , как в большинстве синтаксисов регулярных выражений.

case "$param" in
  *[!\ ]*) echo "\$param contains characters other than space";;
  *) echo "\$param consists of spaces only";;
esac

Для проверки наличия пробелов синтаксис $ '…' специфичен для ksh / bash / zsh; вы можете вставить эти символы в свой скрипт буквально (обратите внимание, что новая строка должна быть в кавычках, поскольку обратная косая черта + новая строка заменяется на ничего) или сгенерировать их, например

whitespace=$(printf '\n\t ')
case "$param" in
  *[!$whitespace]*) echo "\$param contains non-whitespace characters";;
  *) echo "\$param consists of whitespace only";;
esac
32
27.01.2020, 19:27

POSIXly:

case $var in
  (*[![:blank:]]*) echo '$var contains non blank';;
  (*) echo '$var contains only blanks or is empty or unset'
esac

Провести различие между пустым , незаполненным , пустым , незаполненным :

.
case ${var+x$var} in
  (x) echo empty;;
  ("") echo unset;;
  (x*[![:blank:]]*) echo non-blank;;
  (*) echo blank
esac

[:blank:] предназначено для символов с горизонтальным интервалом (пробел и табуляция в ASCII, но, вероятно, есть еще несколько в вашей локали; некоторые системы будут включать неразрывное пространство (если оно доступно), некоторые нет). Если вам нужны также вертикальные символы интервала (например, newline или form-feed), замените [:пробел:] на [:пробел:].

21
27.01.2020, 19:27
if [[ -n "${variable_name/[ ]*\n/}" ]]
then
    #execute if the the variable is not empty and contains non space characters
else
    #execute if the variable is empty or contains only spaces
fi
5
27.01.2020, 19:27

Попробуйте это:

$ [[ -z \`echo $n\` ]] && echo zero

zero
-1
27.01.2020, 19:27

Код, который вы разместили [[ ! -z $param ]] && echo "I am not zero", будет печатать I am not zero, если параметр не установлен/не определен или пуст (в bash, ksh и zsh ).

Для также печатать, если параметр содержит только пробелы (удалить пробелы ), POSIXly (для более широкого диапазона оболочек):

 [   -z "${param#"${param%%[! ]*}"}"   ] && echo "empty"

Пояснение:

  • ${param# … }удаляет начальный текст.
  • Этот ведущий текст дан:${param%%[! ]*}
  • Который расширяется до всех пробелов перед любым не -пробелом символом, то есть всеми ведущими пробелами.

Конечным результатом всего расширения является удаление всех ведущих пробелов.

Этот расширенный результат проверяется, если его длина равна 0.

  • Если результат пустой, то либо переменная была пустой, либо
  • удаление начальных пробелов сделало его пустым.

Следовательно, если проверка верна, переменная либо уже была пустой, либо содержала только пробелы внутри.


Эту концепцию легко распространить на другие типы символов. Чтобы также включить вкладки, поместите явную вкладку внутри выражения в квадратных скобках :

.
 [ -z "${param#"${param%%[!     ]*}"}" ] && echo "empty"

или используйте переменную с удаленными символами, которые вам нужны:

 var=$' \t'                                    # in ksh, bash, zsh
 [ -z "${param#"${param%%[!$var]*}"}" ] && echo "empty"

или вы можете использовать некоторое «выражение класса символов» POSIX (пробел означает пробел и табуляцию):

 [ -z "${param#"${param%%[![:blank:]]*}"}" ] && echo "empty"
1
27.01.2020, 19:27

Чтобы проверить, содержит ли переменная только пробелы, в том числе в многострочной -строковой переменной , попробуйте:

[[ $var = *[$" \t\n"]* ]]

Или с xargs:

[[ -z $(echo $var | xargs) ]]

Или с sed:

[[ -z $(sed "/^$/d" <<< $var) ]]
1
06.05.2020, 15:25

Теги

Похожие вопросы