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


21

Я читаю баш сценарій, я не розумію, що там відбувається.

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

Що відбувається на другому рядку і що [ x$1 = x ] означає?

Відповіді:


27

Це перевіряє, що $1це порожньо, хоча його слід цитувати (ідентично [ -z "$1" ]). Деякі дуже старі оболонки не обробляють порожні рядки належним чином, тому автори портативних сценаріїв прийняли цей стиль перевірки. Це не було потрібно десятиліттями, але люди все одно роблять це так, тому що люди все ще роблять це так.


Так, вам більше не слід так робити і приймати більш сучасний стиль. Якщо ви не працюєте над PDP11.
MacLemon

4
Справа не стільки в порожніх рядках. [ x$1 = x ]по - , як і раніше неправильно, але [ "x$1" = x ]було б для оболонок , які мають проблеми , де $1є !або (чи -n.... [ "" = "$1" ]і case $1 in "")буде також нормально , хоча.
Стефан Шазелас

2
@MacLemon, не потрібно їхати так далеко назад. [ -z "$1" ]і [ "$1" = "" ]досі не працюють з / bin / sh Solaris 10, колишнім тире-0.5.4.
Стефан Шазелас

1
додаткові +1 за останнє речення!
glenn jackman

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-й пункт).
goldilocks

вам не потрібно , ifщоб використання test, ви можете використовувати його раніше &&, ||або після whileабо перевірити результат з допомогою$?
Ясна

8
[ x$1 = x ]

Має сенс тільки в zsh. Це порівнює конкатенацію xпершого аргументу сценарію з x. Отже [команда повертає true, якщо $1вона порожня або не надана.

[ $1 = "" ]

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

У снарядах Борна / POSIX [ x$1 = x ]не має сенсу. Ось оператор split + glob якось застосував до конкатенації xта першого аргументу сценарію, сподіваючись, що результат і =та x, і ]складе дійсний тестовий вираз для [команди.

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

Якщо $1були "* *", то оболонка буде перейти до [команді список файлів в поточному каталозі, ім'я якого починається з x(розширенням Глоби в x*), то перелік не-приховані файли (розширення *) ... що [навряд чи зможемо щоб не було сенсу. Єдині випадки, коли це може зробити щось розумне, це якщо $1він не містить символів підстановки чи порожніх символів.

Тепер те, що ви іноді знаходите, такий код:

[ "x$1" = x ]

Це використовується для перевірки, чи $1порожній або невідомий.

Нормальний спосіб перевірити наявність порожньої чи невстановленої змінної:

[ -z "$1" ]

Але це не вдається для деяких значень, $1як =у деяких (не-POSIX) [реалізаціях, таких як вбудований в оболонці Bourne, як знайдено в /bin/shSolaris 10 і раніше, або деяких старих версіях dash(до 0,5.4) або shдеяких BSD.

Це тому , що [бачить [, -z, =, ]і скаржиться на відсутні аргументи =бінарного оператора замість розуміння його як -zунарний оператор застосовується до =рядку.

Аналогічно, відбувається [ "$1" = "" ]збій для деяких реалізацій [if $1є !або (.

У цих оболонках / [реалізаціях:

[ "x$1" = x ]

завжди є дійсним тестом незалежно від значення $1, тому:

[ "" = "$1" ]

і:

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

і

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

Звичайно, якщо ви хочете перевірити, чи не наводиться аргумент, ви зробите:

[ "$#" -eq 0 ]

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

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


0

x$1є об'єднанням двох рядків xі, $1якщо $ 1 порожній, x $ 1 дорівнює x, і [x $ 1 = x] буде істинним. x = yвикористовується для порівняння рядків у ш


2
Ні x$1, не котирується, тому розщеплення та глобалізація виконується на тих.
Стефан Шазелас

0

[ x$1 = x ]вірно, якщо він $1не встановлений / null / порожній чи ні.
Спробуйте себе:
TEST= ;[ x$TEST = x] && echo "TEST is unset"
і
TEST=lolz ;[ x$TEST = x ] && echo "TEST is unset"


1
[ x$1 = x ]також вірно, якщо $1є, наприклад " -o x". Спробуйте sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]помиляється і не має сенсу.
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.