2009-07-07 13 views
22

Sto provando a confrontare due stringhe in un semplice script di shell. Stavo usando /bin/sh invece di /bin/bash, e dopo innumerevoli ore di debugging, si scopre sh (che è in realtà trattino), non in grado di gestire questo blocco di codice:confronto bash, trattini e stringhe

if [ "$var" == "string" ] 
then 
    do something 
fi 

cosa è un modo portabile per confrontare le stringhe utilizzando /bin/sh? So che posso sempre fare il contrario usando! =, Ma mi sto chiedendo un modo più pulito e portatile.

+2

È possibile utilizzare '[[$ var ==" stringa "]]', che è POSIX, ma facoltativo (afaik). O usi '[" $ var "=" stringa "]'. Notare il '" "' attorno alla variabile nell'edizione single-bracket: è necessario nel caso in cui '$ var' sia vuoto –

+0

La parte importante sono le virgolette intorno a' $ var' come menzionato in precedenza. Senza le virgolette, '[$ var =" value "]' diventa '[=" value "]' che confonde la shell in modo abbastanza orribile. Probabilmente vedrai un errore come _ "[: =: unario operatore previsto" _ quando incontrerai una variabile vuota altrimenti. –

+0

Comprendo "$ var" rispetto a $ var, il mio problema era == vs. = – LiraNuna

risposta

32

dash è una shell POSIX molto severo, se lavorare in dash è quasi certo che avrebbe funzionato in altre shell POSIX.

Prova:

if [ "$var" = "string" ] 
then 
    some_command 
fi 
8

Perché esiste anche la possibilità che lo script venga eseguito dalla shell "errata"? Vorrei pensare si potrebbe fare che un pre-requisito del vostro prodotto utilizzando la linea sh-bang di serie nella parte superiore dello script:

#!/bin/bash 

Anche se un utente utilizza una shell diversa, le altre shell sono generalmente ancora lì e, in caso contrario, si lamentano semplicemente e affermano che sono pre-req.

Esattamente nello stesso modo in cui uno specifico livello del kernel o l'esistenza di awk può essere un pre-req.

Per la vostra domanda specifica, credo che sia sh e bash consentire al singolo '=' da utilizzare per i confronti di stringhe - che è il comportamento POSIX:

if [ "a" = "a" ] ; then 
    echo yes 
fi 

yes 
+1

* "Perché c'è anche una possibilità che il tuo script venga eseguito dalla shell" sbagliata? "* - È possibile controllare quale shell è usata da Autoconf? (Questo è il motivo per cui sto cercando la risposta) – jww

3

Uso = invece di ==. I confronti sono gestiti dal test (1). /usr/bin/[ è in genere un collegamento a /usr/bin/test. L'unica differenza è che se si utilizza [ in uno script di shell, è richiesto anche lo ].

Nota che bash ha uno test/[ integrato, quindi non utilizza effettivamente /usr/bin/test.

-3

si può usare awk

awk 'BEGIN{ 
string1="test" 
string2="tes1t" 
if(s1==s2){ 
    print "same string" 
}else{ 
    print "not same" 
} 
}' 
1

Le risposte già postato sono certamente corretto, ma può valere la pena di notare che l'espansione di tanto in tanto parametro può servire allo stesso scopo con forse qualche ulteriore flessibilità.

% p() { printf 'notvar = %b\n' "${notvar##"${string1}"}${string2}" ; } 
% string1='some stuff about things\c' 
% string2='some different stuff maybe' 
% notvar="$string1" p 
> 'some different stuff maybe' 
% notvar="$string2" p 
> 'some stuff about things' 

Ok, quindi quanto sopra non è super-utile come è, ma considerano anche che è possibile utilizzare i metodi simili per le variabili di test nel qui-documenti, in linea assegnazioni di variabili, se necessario (ad un grado ...), o anche solo come un mezzo più breve (e più veloce!) di scrivere la tua prima affermazione.

[ ! "${var##"string"}" ] && _MATCH || _NOMATCH 

O anche ...

[ ${#var#*"${s=string}"} -lt ${#var} ] && _SUB_STRING_TEST=TRUE 

Forse anche ...

% p() { printf '%s is %s of %s' "$2" "${var_chk-not}" "$1" 
> }<<HEREDOC 
> ${in="${1##*"${2}"*}"} 
> ${in:- 
>  ${in="${1##"${2}"}"} 
>  ${in:-${var_chk=all} 
>  ${var_chk=some} 
> } 
> HEREDOC 
% 
+1

Non sono sicuro di vedere il grande vantaggio di queste tecniche a meno che tu non stia cercando di vincere un concorso di offuscamento. – swdev