script bash [x $ 1 = x]


21

Sto leggendo la sceneggiatura di Bash, non capisco cosa stia succedendo lì.

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

Cosa sta succedendo sulla seconda linea e cosa [ x$1 = x ] significa?

Risposte:


27

Che controlla che $1sia vuoto, anche se dovrebbe essere citato (identico a [ -z "$1" ]). Alcune shell molto vecchie non gestivano correttamente le stringhe vuote, quindi gli autori di script portatili hanno adottato questo stile di controllo. Non è stato necessario per decenni, ma la gente lo fa ancora così perché la gente lo fa ancora così.


Sì, non dovresti più farlo così e adottare uno stile più moderno. A meno che tu non stia lavorando su un PDP11.
MacLemon,

4
Non si tratta tanto di stringhe vuote. [ x$1 = x ]non è ancora corretta, ma [ "x$1" = x ]sarebbe per conchiglie che hanno un problema in cui $1è !o (o -n.... [ "" = "$1" ]e case $1 in "")sarebbe anche però OK.
Stéphane Chazelas,

2
@MacLemon, non c'è bisogno di andare così indietro. [ -z "$1" ]e [ "$1" = "" ]ancora non funziona con / bin / sh di Solaris 10, il primo con trattino-0.5.4.
Stéphane Chazelas,

1
+1 extra per l'ultima frase!
Glenn Jackman,

1
@glennjackman, l'ultima frase non è corretta. Solaris 10 è ancora la versione più diffusa di Solaris e [ "$1" = "" ]non funziona ancora con essa /bin/sh(anche se non si desidera utilizzarla /usr/xpg4/bin/sh/bin/sh). trattino è stato fissato a tale proposito nel gennaio 2009.
Stéphane Chazelas,

8

Le parentesi quadre indicano un test , quindi [ x$1 = x]senza ifo qualcosa di simile è insignificante, anche se sintatticamente ok.

Ha lo scopo di valutare vero se si x$1espande xe falso altrimenti, ma poiché non è quotato, se $1è (es.) "Hey x", la shell vedrà x = x, quindi questa costruzione non è ancora sicura.

Lo scopo del x = xcontrollo è determinare se una variabile è vuota. Un modo più comune per farlo sarebbe usare solo le virgolette:

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

Operatori di prova Bash -ze -npossono anche essere utilizzati, ma sono meno portabile su altri tipi di conchiglie. 1

La ragione per le virgolette, o il x$1, è che il lato sinistro non si espande in nulla, il che sarebbe un errore sintattico:

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

1. In realtà, testpuò essere un'utilità autonoma ma la maggior parte delle shell la implementa come built-in; controlla la differenza tra which teste type test. Su GNU / Linux man testafferma di fare riferimento al built-in, ma se si chiama (ad es.) /usr/bin/test, Tale utility sembra implementare le funzionalità documentate nella pagina man, incluso -ze -n.


1
[ x$1 = x ]valuterà anche vero se $1è per esempio " -o x". Prova sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]è sbagliato e non ha senso.
Stéphane Chazelas,

@ StéphaneChazelas Grazie SC - modificato (secondo paragrafo).
Riccioli d'oro,

non è necessario ifutilizzare test, è possibile utilizzarlo prima &&, ||o dopo whileo esaminare il risultato utilizzando$?
Jasen,

8
[ x$1 = x ]

Ha senso solo dentro zsh. Ciò confronta la concatenazione di xcon il primo argomento della sceneggiatura con x. Quindi il [comando restituisce true se $1è vuoto o non fornito.

[ $1 = "" ]

Non avrebbe funzionato perché, in zshquando una variabile vuota, non è citato in contesti della lista, si espande per alcun argomento a tutti, invece di un argomento vuoto, quindi se $1fosse impostata o svuotare, il [comando sarà solo ricevere come argomenti [, =la stringa vuota e da ]cui non ha senso. [ -z "$1" ]o [ "$1" = "" ]sarebbe OK anche se come nelle shell POSIX.

Nelle shell / POSIX tipo Bourne, [ x$1 = x ]non ha senso. Questo è l'operatore split + glob in qualche modo applicato alla concatenazione xe al primo argomento dello script sperando che il risultato e =e x, e, ]costituisca una valida espressione di test per il [comando.

Per esempio, se lo script è stato passato un " = x -o x ="argomento, [avrebbe ricevuto questi argomenti: [, x, =, x, -o, x, =, x, ], che [avrebbe capito come il confronto xcon xe xcon xe restituire true.

Se lo $1fosse "* *", la shell passerebbe al [comando l'elenco dei file nella directory corrente il cui nome inizia con x(l'espansione glob di x*), quindi l'elenco dei file non nascosti (espansione *) ... che [difficilmente sarà in grado per dare un senso a. Gli unici casi in cui ciò farebbe qualcosa di sensato è se $1non contiene caratteri jolly o caratteri vuoti.

Ora, ciò che a volte trovi è il codice come:

[ "x$1" = x ]

Viene utilizzato per verificare se $1è vuoto o non impostato.

Il modo normale di testare una variabile vuota o non impostata è:

[ -z "$1" ]

Ma ciò fallisce per alcuni valori di $1like =in alcune [implementazioni (non POSIX) come quella incorporata nella shell Bourne come /bin/shsu Solaris 10 e precedenti o su alcune vecchie versioni di dash(fino a 0.5.4) o shsu alcuni BSD.

Questo perché [vede [, -z, =, ]e si lamenta di argomenti mancante alla =operatore binario, invece di capire come l' -zoperatore unario applicato alla =stringa.

Allo stesso modo, [ "$1" = "" ]fallisce per alcune implementazioni di [if $1is !or (.

In quelle shell / [implementazioni:

[ "x$1" = x ]

è sempre un test valido indipendentemente dal valore di $1, quindi sono:

[ "" = "$1" ]

e:

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

e

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

Naturalmente, se si desidera verificare che non venga fornito alcun argomento, è necessario:

[ "$#" -eq 0 ]

Cioè, controlli il numero di argomenti passati allo script.

Si noti che al giorno d'oggi, [ -z "$var" ]è chiaramente specificato da POSIX e non può fallire in conformant [implementazioni (e bashs' [è ed è stato per decenni). Quindi dovresti essere in grado di fare affidamento su di esso in sh o bashscript POSIX .


0

x$1sta concatenando due stringhe xe $1e se $ 1 è vuoto, x $ 1 è uguale a x e, di conseguenza, [x $ 1 = x] sarà vero. x = yè usato per confrontare la stringa in sh


2
No x$1non viene citato, quindi su questi viene eseguita la divisione e il globbing.
Stéphane Chazelas,

0

[ x$1 = x ]è vero se $1è disinserito / null / vuoto o no.
Mettiti alla prova con:
TEST= ;[ x$TEST = x] && echo "TEST is unset"
e
TEST=lolz ;[ x$TEST = x ] && echo "TEST is unset"


1
[ x$1 = x ]è anche vero se $1è per esempio " -o x". Prova sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]è sbagliato e non ha senso.
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.