2009-07-07 8 views
22

J'essaie de comparer deux chaînes dans un simple script shell. j'utilisais /bin/sh au lieu de /bin/bash, et après d'innombrables heures de débogage, il se trouve sh (qui est en fait tableau de bord) ne peut pas gérer ce bloc de code:comparaison de bash, dash et string

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

Qu'est-ce qu'un moyen portable pour comparer des chaînes en utilisant /bin/sh? Je sais que je peux toujours faire le contraire en utilisant! =, Mais je m'interroge sur une façon plus propre et portable.

+2

Vous pouvez utiliser '[[$ var ==" string "]]', qui est POSIX, mais optionnel (afaik). Ou vous utilisez '[" $ var "=" string "]'. Notez le '" "' autour de la variable dans l'édition à un seul crochet: c'est obligatoire dans le cas où '$ var' est vide –

+0

La partie importante est les guillemets autour de' $ var' comme litb mentionné. Sans les guillemets, '[$ var =" valeur "]' devient '[=" valeur "]', ce qui rend le shell assez terrifiant. Vous verrez probablement une erreur comme _ "[: =: opérateur unaire attendu" _ lorsque vous rencontrez une variable vide sinon. –

+0

Je comprends à propos de "$ var" vs $ var, mon problème était == vs = – LiraNuna

Répondre

32

dash est un shell POSIX très strict, s'il fonctionne en dash il est presque certain qu'il fonctionnerait dans un autre shell POSIX.

Essayez:

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

Pourquoi est-il même possible que votre script soit exécuté par le "mauvais" shell? Je pense que vous pourriez en faire une condition préalable de votre produit en utilisant la norme ligne sh-bang en haut de votre script:

#!/bin/bash 

Même si un utilisateur utilise une coque différente, les autres coquilles sont généralement toujours là et, si non, simplement se plaindre et déclarer qu'ils sont un pré-req.

Exactement de la même manière qu'un niveau de noyau spécifique, ou l'existence de awk, peut être un pré-requis.

Pour votre question, je crois que les deux sh et bash permettent le single '=' à utiliser pour les comparaisons de chaînes - c'est un comportement POSIX:

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

yes 
+1

* "Pourquoi est-il même possible que votre script soit exécuté par le" mauvais "shell?" * - Est-il possible de contrôler quel shell est utilisé par Autoconf? (C'est la raison pour laquelle je cherche la réponse) – jww

3

Utilisation = au lieu de ==. Les comparaisons sont traitées par test (1). /usr/bin/[ est généralement un lien vers /usr/bin/test. La seule différence est que si vous utilisez [ dans un script shell, le ] est également requis. Notez que bash a un test/[ intégré, donc il n'utilise pas réellement /usr/bin/test.

-3

vous pouvez utiliser awk

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

Les réponses déjà affichées sont certainement correct, mais il peut être intéressant de noter que l'expansion de temps en temps paramètre peut servir le même but avec peut-être une certaine flexibilité supplémentaire.

% 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, donc ce qui précède n'est pas super utile comme il est, mais aussi considérer que vous pouvez utiliser les méthodes similaires pour les variables de test ici-documents, les affectations de variables en ligne si nécessaire (à un degré ...), ou même comme un moyen plus court (et plus rapide!) d'écrire votre première déclaration.

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

Ou encore ...

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

Peut-être même ...

% 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

Je ne suis pas sûr de voir le grand avantage de ces techniques, sauf si vous essayez de gagner un concours d'obfuscation. – swdev