skrypt bash [x $ 1 = x]


21

Czytam skrypt bash Nie rozumiem, co się tam dzieje.

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

Co dzieje się na drugiej linii i co to [ x$1 = x ] znaczy?

Odpowiedzi:


27

To sprawdza, które $1są puste, choć powinny być cytowane (identycznie jak [ -z "$1" ]). Niektóre bardzo stare powłoki nie obsługiwały poprawnie pustych łańcuchów, więc autorzy skryptów przenośnych przyjęli ten styl sprawdzania. Nie było to konieczne od dziesięcioleci, ale ludzie nadal robią to w ten sposób, ponieważ ludzie nadal tak robią.


Tak, nie powinieneś już tego robić w ten sposób i przyjmować bardziej nowoczesny styl. Chyba że pracujesz na PDP11.
MacLemon

4
Nie chodzi tak bardzo o puste ciągi. [ x$1 = x ]jest nadal niepoprawny, ale [ "x$1" = x ]dotyczyłby powłok, które mają problem z gdzie $1jest !lub (lub -n.... [ "" = "$1" ]i case $1 in "")również byłyby OK.
Stéphane Chazelas

2
@MacLemon, nie musisz cofać się tak daleko. [ -z "$1" ]i [ "$1" = "" ]nadal nie działa z / bin / sh Solaris 10, poprzedni z dash-0.5.4.
Stéphane Chazelas,

1
dodatkowe +1 za ostatnie zdanie!
glenn jackman

1
@glennjackman, to ostatnie zdanie jest nieprawidłowe. Solaris 10 nadal jest najbardziej powszechnie stosowane wersja Solaris i [ "$1" = "" ]nadal nie działa z jego /bin/sh(choć tylko chcesz używać /usr/xpg4/bin/shtam, nie /bin/sh). kres został naprawiony w tym względzie w styczniu 2009 r.
Stéphane Chazelas

8

Nawiasy kwadratowe wskazują na test , więc [ x$1 = x]bez iflub coś podobnego jest bez znaczenia, chociaż składniowo ok.

Ma on oceniać jako prawda, jeśli x$1rozwija się x, a w przeciwnym razie fałsz, ale ponieważ nie jest cytowany, jeśli $1jest (np.) „Hej x”, powłoka zobaczy x = x, więc ta konstrukcja nadal nie jest bezpieczna.

Celem tego x = xsprawdzenia jest ustalenie, czy zmienna jest pusta. Częstszym sposobem na to byłoby po prostu użycie cudzysłowów:

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

Operatorzy testowe bash -zi -nmoże być również używany, ale są one mniej przenośne do innych rodzajów muszli. 1

Powodem cytowania lub tego x$1jest to, że lewa strona nie rozwija się do zera, co byłoby błędem składniowym:

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

1. W rzeczywistości testmoże być samodzielnym narzędziem, ale większość powłok implementuje je jako wbudowane; sprawdź różnicę między which testi type test. W GNU / Linux man testtwierdzi, że odnosi się do wbudowanego, ale jeśli wywołasz (np.) /usr/bin/test, To narzędzie wydaje się implementować funkcje udokumentowane na stronie podręcznika, w tym -zi -n.


1
[ x$1 = x ]oceni również prawdę, jeśli tak $1jest na przykład " -o x". Spróbować sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]jest zły i nie ma sensu.
Stéphane Chazelas

@ StéphaneChazelas Thanks SC - edytowany (2. akapit).
goldilocks

nie musisz ifgo używać test, możesz go użyć przed &&, ||po whilelub sprawdzić wynik za pomocą$?
Jasen

8
[ x$1 = x ]

Ma to sens tylko w zsh. To porównuje konkatenację xz pierwszym argumentem skryptu do x. Tak więc [polecenie zwraca true, jeśli $1jest puste lub nie zostało podane.

[ $1 = "" ]

Nie działałoby, ponieważ zshgdy pusta zmienna nie jest cytowana w kontekstach list, nie rozwija się w ogóle do żadnego argumentu zamiast pustego argumentu, więc gdyby $1były nieustawione lub puste, [polecenie otrzymywałoby tylko jako argumenty [, =pusty ciąg i z ]czego to nie miało sensu. [ -z "$1" ]lub [ "$1" = "" ]byłoby OK, chociaż jak w powłokach POSIX.

W powłokach typu Bourne'a / POSIX [ x$1 = x ]nie ma sensu. To jest operator split + glob w jakiś sposób zastosowany do konkatenacji xi pierwszy argument skryptu, mając nadzieję, że wynik i, =i x, i ]tworzą prawidłowe wyrażenie testowe dla [polecenia.

Na przykład, jeśli skrypt został przekazany jednego " = x -o x ="argumentu, [by otrzymać te argumenty: [, x, =, x, -o, x, =, x, ], który [zrozumie porównać xz xi xz xa return true.

Gdyby tak $1było "* *", to powłoka przekazałaby do [polecenia listę plików w bieżącym katalogu, których nazwa zaczyna się od x(globalne rozszerzenie x*), a następnie listę plików nie ukrytych (rozszerzenie *) ... co [jest mało prawdopodobne z jakiegokolwiek sensu. Jedynymi przypadkami, w których byłoby to sensowne, jest to, $1że nie zawiera symboli wieloznacznych ani pustych znaków.

Teraz czasem znajduje się kod:

[ "x$1" = x ]

Służy do sprawdzania, czy $1jest pusty lub rozbrojony.

Normalny sposób testowania pustej lub nieuzbrojonej zmiennej to:

[ -z "$1" ]

Ale to nie udaje się w przypadku niektórych wartości $1podobnych =w niektórych [implementacjach (nie POSIX), takich jak wbudowana w powłoce Bourne'a, jak znaleziono /bin/shw Solarisie 10 i wcześniejszych wersjach lub niektórych starych wersjach dash(do 0.5.4) lub shniektórych BSD.

To dlatego, że [widzi [, -z, =, ]i narzeka na brak argumentów do =operatora binarnego zamiast zrozumienia go jako -zoperator jednoargumentowy stosowane do =łańcucha.

Podobnie [ "$1" = "" ]nie udaje się w przypadku niektórych implementacji [if $1is !lub (.

W tych powłokach / [implementacjach:

[ "x$1" = x ]

jest zawsze ważnym testem niezależnie od wartości $1, więc są:

[ "" = "$1" ]

i:

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

i

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

Oczywiście, jeśli chcesz sprawdzić, czy nie podano argumentu, wykonaj następujące czynności:

[ "$#" -eq 0 ]

Oznacza to, że sprawdzasz liczbę argumentów przekazanych do skryptu.

Należy zauważyć, że w dzisiejszych czasach, [ -z "$var" ]jest jasno określony przez POSIX i nie może zabraknąć w zgodnymi [wdrożeń (a bash„s [jest i był przez dziesięciolecia). Powinieneś więc móc polegać na nim w POSIX sh lub bashskryptach.


0

x$1jest łączeniem dwóch łańcuchów, xa $1jeśli $ 1 jest pusty, x $ 1 równa się x, a [x $ 1 = x] będzie w rezultacie prawdziwe. x = ysłuży do porównywania napisów w sh


2
Nie x$1nie jest cytowany, więc dzielenie i globowanie jest wykonywane na nich.
Stéphane Chazelas

0

[ x$1 = x ]ma wartość true, jeśli $1jest nieustawione / zerowe / puste lub nie.
Wypróbuj się z:
TEST= ;[ x$TEST = x] && echo "TEST is unset"
i
TEST=lolz ;[ x$TEST = x ] && echo "TEST is unset"


1
[ x$1 = x ]jest również prawdą, jeśli tak $1jest na przykład " -o x". Spróbować sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]jest zły i nie ma sensu.
Stéphane Chazelas
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.