Come verificare se una stringa contiene una sottostringa in Bash


2573

Ho una stringa in Bash:

string="My string"

Come posso verificare se contiene un'altra stringa?

if [ $string ?? 'foo' ]; then
  echo "It's there!"
fi

Dov'è il ??mio operatore sconosciuto. Uso echo e grep?

if echo "$string" | grep 'foo'; then
  echo "It's there!"
fi

Sembra un po 'goffo.


4
Ciao, se le stringhe vuote sono false, perché lo consideri goffo? È stato l'unico modo che ha funzionato per me, nonostante le soluzioni proposte.
ericson.cepeda,

1
È possibile utilizzare il exprcomando qui
cli__

4
Ecco uno per le shell POSIX: stackoverflow.com/questions/2829613/...
sehe

Risposte:


3656

Puoi usare la risposta di Marcus (* caratteri jolly) anche al di fuori di un'istruzione case, se usi parentesi doppie:

string='My long string'
if [[ $string == *"My long"* ]]; then
  echo "It's there!"
fi

Si noti che gli spazi nella stringa dell'ago devono essere inseriti tra virgolette doppie e che i *caratteri jolly devono essere esterni. Si noti inoltre che viene utilizzato un semplice operatore di confronto (ovvero ==), non l'operatore regex =~.


127
Si noti inoltre che è possibile invertire il confronto semplicemente passando a! = Nel test. Grazie per la risposta!
Quinn Taylor,

63
@Jonik: potresti perdere lo shebang o averlo come #!/bin/sh. Prova #!/bin/bashinvece.
In pausa fino a nuovo avviso.

10
Lascia uno spazio tra le parentesi e il contenuto.
Paul Price,

17
Non è necessario citare le variabili all'interno di [[]].
Funzionerà

13
@Orwellophile Attenzione! Puoi solo omettere le doppie virgolette nel primo argomento a [[. Vedi ideone.com/ZSy1gZ
nyuszika7h

612

Se preferisci l'approccio regex:

string='My string';

if [[ $string =~ "My" ]]
then
   echo "It's there!"
fi

2
Ho dovuto sostituire un regex egrep in uno script bash, ha funzionato perfettamente!
blast_hardcheese,

114
L' =~operatore cerca già una corrispondenza nell'intera stringa; le .*'s qui sono estranei. Inoltre, le virgolette sono generalmente preferibili alle barre rovesciate:[[ $string =~ "My s" ]]
bukzor

16
@bukzor Le citazioni hanno smesso di funzionare qui a partire da Bash 3.2+: tiswww.case.edu/php/chet/bash/FAQ E14) . Probabilmente è meglio assegnare a una variabile (usando le virgolette), quindi confrontare. In questo modo:re="My s"; if [[ $string =~ $re ]]
seanf,

36
Verifica se NON contiene una stringa: if [[ ! "abc" =~ "d" ]]è vero.
KrisWebDev,

1
Si noti che l'ordine in cui si verifica il test è importante. L'output della seguente riga di codice verrà inoltrato 2.number=2; if [[ "1, 2, 4, 5" = *${number}* ]]; then echo forward $number; fi; if [[ *${number}* = "1, 2, 4, 5" ]]; then echo backwards $number; fi;
Douwe van der Leest

357

Non sono sicuro di usare un'istruzione if, ma puoi ottenere un effetto simile con un'istruzione case:

case "$string" in 
  *foo*)
    # Do stuff
    ;;
esac

76
Questa è probabilmente la soluzione migliore poiché è portatile per posix shell. (aka no bashisms)
technosaurus

25
@technosaurus Trovo piuttosto strano criticare il "bashismo" in una domanda che ha solo il tag bash :)
PP,

39
@PP Non è tanto una critica quanto la preferenza di una soluzione più universale rispetto a una più limitata. Tieni presente che, anni dopo, le persone (come me) si fermeranno per cercare questa risposta e potrebbero essere contente di trovarne una utile in un ambito più ampio rispetto alla domanda originale. Come si dice nel mondo Open Source: "la scelta è buona!"
Carl Smotricz,

2
@technosaurus, FWIW [[ $string == *foo* ]]funziona anche in alcune versioni sh compatibili con POSIX (ad es. /usr/xpg4/bin/shsu Solaris 10) e ksh (> = 88)
maxschlepzig

3
Busybox ash non gestisce gli asterischi in [[... l'interruttore del case ha funzionato!
Ray Foss

232

stringContain varianti (compatibile o indipendente dal caso)

Dato che queste risposte di Stack Overflow parlano principalmente di Bash , ho pubblicato un caso indipendente funzione Bash in fondo a questo post ...

Comunque, c'è il mio

Risposta compatibile

Dato che ci sono già molte risposte usando le funzionalità specifiche di Bash, c'è un modo di lavorare con shell con funzionalità scadenti, come BusyBox :

[ -z "${string##*$reqsubstr*}" ]

In pratica, questo potrebbe dare:

string='echo "My string"'
for reqsubstr in 'o "M' 'alt' 'str';do
  if [ -z "${string##*$reqsubstr*}" ] ;then
      echo "String '$string' contain substring: '$reqsubstr'."
    else
      echo "String '$string' don't contain substring: '$reqsubstr'."
    fi
  done

Questo è stato testato su Bash, Dash , KornShell ( ksh) e ash (BusyBox) e il risultato è sempre:

String 'echo "My string"' contain substring: 'o "M'.
String 'echo "My string"' don't contain substring: 'alt'.
String 'echo "My string"' contain substring: 'str'.

In una funzione

Come richiesto da @EeroAaltonen, ecco una versione della stessa demo, testata con le stesse shell:

myfunc() {
    reqsubstr="$1"
    shift
    string="$@"
    if [ -z "${string##*$reqsubstr*}" ] ;then
        echo "String '$string' contain substring: '$reqsubstr'.";
      else
        echo "String '$string' don't contain substring: '$reqsubstr'."
    fi
}

Poi:

$ myfunc 'o "M' 'echo "My String"'
String 'echo "My String"' contain substring 'o "M'.

$ myfunc 'alt' 'echo "My String"'
String 'echo "My String"' don't contain substring 'alt'.

Avviso: devi scappare o racchiudere tra virgolette e / o virgolette doppie:

$ myfunc 'o "M' echo "My String"
String 'echo My String' don't contain substring: 'o "M'.

$ myfunc 'o "M' echo \"My String\"
String 'echo "My String"' contain substring: 'o "M'.

Funzione semplice

Questo è stato testato sotto BusyBox, Dash e, ovviamente, Bash:

stringContain() { [ -z "${2##*$1*}" ]; }

Quindi ora:

$ if stringContain 'o "M3' 'echo "My String"';then echo yes;else echo no;fi
no
$ if stringContain 'o "M' 'echo "My String"';then echo yes;else echo no;fi
yes

... O se la stringa inviata potesse essere vuota, come sottolineato da @Sjlver, la funzione diventerebbe:

stringContain() { [ -z "${2##*$1*}" ] && [ -z "$1" -o -n "$2" ]; }

o come suggerito dal commento di Adrian Günter , evitando -ointerruzioni:

stringContain() { [ -z "${2##*$1*}" ] && { [ -z "$1" ] || [ -n "$2" ];};}

Funzione (semplice) finale:

E invertendo i test per renderli potenzialmente più veloci:

stringContain() { [ -z "$1" ] || { [ -z "${2##*$1*}" ] && [ -n "$2" ];};}

Con stringhe vuote:

$ if stringContain '' ''; then echo yes; else echo no; fi
yes
$ if stringContain 'o "M' ''; then echo yes; else echo no; fi
no

Caso indipendente (solo Bash!)

Per testare le stringhe senza preoccuparsi del caso, è sufficiente convertire ciascuna stringa in minuscolo:

stringContain() {
    local _lc=${2,,}
    [ -z "$1" ] || { [ -z "${_lc##*${1,,}*}" ] && [ -n "$2" ] ;} ;}

Dai un'occhiata:

stringContain 'o "M3' 'echo "my string"' && echo yes || echo no
no
stringContain 'o "My' 'echo "my string"' && echo yes || echo no
yes
if stringContain '' ''; then echo yes; else echo no; fi
yes
if stringContain 'o "M' ''; then echo yes; else echo no; fi
no

1
Sarebbe ancora meglio se riuscissi a trovare un modo per metterlo in funzione.
Eero Aaltonen,

2
@EeroAaltonen Come trovi la mia (nuova aggiunta) funzione?
F. Hauri,

2
Lo so! trova . -name "*" | xargs grep "myfunc" 2> / dev / null
eggmatters

6
Questo è meraviglioso perché è così compatibile. Un bug, però: non funziona se la stringa del pagliaio è vuota. La versione corretta sarebbe string_contains() { [ -z "${2##*$1*}" ] && [ -n "$2" -o -z "$1" ]; } un pensiero finale: la stringa vuota contiene la stringa vuota? La versione sopra è sì (a causa della -o -z "$1"parte).
Sjlver,

3
+1. Molto bene! Per me ho cambiato l'ordine stringContain () {[-z "$ {1 ## * $ 2 *}"] && [-z "$ 2" -o -n "$ 1"]; }; "Cerca dove" "Trova cosa". Lavora in busybox. La risposta accettata sopra non funziona in busybox.
user3439968

149

Dovresti ricordare che lo scripting della shell è meno di una lingua e più di una raccolta di comandi. Istintivamente pensi che questo "linguaggio" richieda di seguire un ifcon un [o un [[. Entrambi sono solo comandi che restituiscono uno stato di uscita che indica l'esito positivo o negativo (proprio come ogni altro comando). Per questo motivo userei grep, e non il [comando.

Basta fare:

if grep -q foo <<<"$string"; then
    echo "It's there"
fi

Ora che stai pensando di iftestare lo stato di uscita del comando che lo segue (completo di punti e virgola), perché non riconsiderare l'origine della stringa che stai testando?

## Instead of this
filetype="$(file -b "$1")"
if grep -q "tar archive" <<<"$filetype"; then
#...

## Simply do this
if file -b "$1" | grep -q "tar archive"; then
#...

L' -qopzione fa in modo che grep non produca nulla, poiché vogliamo solo il codice di ritorno. <<<fa sì che la shell espanda la parola successiva e la usi come input per il comando, una versione di una riga del <<documento qui (non sono sicuro che si tratti di uno standard o di un Bashismo).


7
si chiamano qui stringhe (3.6.7) Credo che sia basismo
alex.pilon,

10
si può anche usare Sostituzione processo if grep -q foo <(echo somefoothing); then
larsr

Nota che non echoè portabile, se stai passando una variabile, usa printf '%s' "$stringinvece.
nyuszika7h,

5
Il costo di questo è molto costoso: fare grep -q foo <<<"$mystring"implie 1 fork ed è bashism e echo $mystring | grep -q fooimplie 2 forchette (una per la pipa e la seconda per la corsa /path/to/grep)
F. Hauri

1
@BrunoBronosky echosenza flag potrebbe avere ancora problemi di portabilità imprevisti se la stringa dell'argomento contiene sequenze di barre rovesciate. echo "nope\c"è previsto che su alcune piattaforme funzioni come echo -e "nope"su altre. printf '%s' "nope"vsprintf '%s\n' 'nope\c'
tripleee

92

La risposta accettata è la migliore, ma poiché esiste più di un modo per farlo, ecco un'altra soluzione:

if [ "$string" != "${string/foo/}" ]; then
    echo "It's there!"
fi

${var/search/replace}è $varcon la prima istanza di searchsostituito da replace, se viene trovato (non cambia $var). Se si tenta di sostituire fooper nulla e la stringa è cambiata, ovviamente è foostato trovato.


5
la soluzione di ephemient sopra:> `if [" $ string "! =" $ {string / foo /} "]; quindi echo "È lì!" fi` è utile quando si utilizza la shell ash di BusyBox . La soluzione accettata non funziona con BusyBox perché alcune espressioni regolari di bash non sono implementate.
TPoschel

1
la disuguaglianza della differenza. Pensiero abbastanza strano! Lo adoro
nitinr708

1
a meno che la tua stringa non sia "foo", però
venimus,

Ho scritto questa stessa soluzione (perché il mio interprete non avrebbe preso le risposte migliori) poi sono andato alla ricerca di una migliore, ma ho trovato questo!
BuvinJ,

56

Quindi ci sono molte soluzioni utili alla domanda, ma qual è la più veloce / utilizza il minor numero di risorse?

Test ripetuti usando questo frame:

/usr/bin/time bash -c 'a=two;b=onetwothree; x=100000; while [ $x -gt 0 ]; do TEST ; x=$(($x-1)); done'

Sostituzione di TEST ogni volta:

[[ $b =~ $a ]]           2.92 user 0.06 system 0:02.99 elapsed 99% CPU

[ "${b/$a//}" = "$b" ]   3.16 user 0.07 system 0:03.25 elapsed 99% CPU

[[ $b == *$a* ]]         1.85 user 0.04 system 0:01.90 elapsed 99% CPU

case $b in *$a):;;esac   1.80 user 0.02 system 0:01.83 elapsed 99% CPU

doContain $a $b          4.27 user 0.11 system 0:04.41 elapsed 99%CPU

(doContain era nella risposta di F. Houri)

E per risatine:

echo $b|grep -q $a       12.68 user 30.86 system 3:42.40 elapsed 19% CPU !ouch!

Quindi la semplice opzione di sostituzione vince in modo prevedibile in un test esteso o in un caso. La custodia è portatile.

Piping fuori a 100000 greps è prevedibilmente doloroso! La vecchia regola sull'uso di utility esterne senza necessità è vera.


4
Punto di riferimento pulito. Mi ha convinto a usarlo [[ $b == *$a* ]].
Fisico pazzo,

2
Se sto leggendo correttamente, casevince con il minor consumo di tempo complessivo. Ti manca un asterisco dopo $b in *$aperò. Ottengo risultati leggermente più veloci [[ $b == *$a* ]]rispetto a casequando il bug è stato corretto, ma ovviamente potrebbe dipendere anche da altri fattori.
Tripleee

1
ideone.com/5roEVt ha corretto il mio esperimento con alcuni bug aggiuntivi e test per uno scenario diverso (in cui la stringa non è effettivamente presente nella stringa più lunga). I risultati sono in gran parte simili; [[ $b == *$a* ]]è veloce ed caseè quasi altrettanto veloce (e piacevolmente compatibile con POSIX).
Tripleee

28

Questo funziona anche:

if printf -- '%s' "$haystack" | egrep -q -- "$needle"
then
  printf "Found needle in haystack"
fi

E il test negativo è:

if ! printf -- '%s' "$haystack" | egrep -q -- "$needle"
then
  echo "Did not find needle in haystack"
fi

Suppongo che questo stile sia un po 'più classico, meno dipendente dalle caratteristiche della shell Bash.

L' --argomento è la pura paranoia POSIX, utilizzata per proteggere dalle stringhe di input simili alle opzioni, come --abco -a.

Nota: in un circuito stretto questo codice sarà molto più lento rispetto all'utilizzo delle funzionalità interne della shell Bash, poiché uno (o due) processi separati verranno creati e collegati tramite pipe.


5
... ma l'OP non dice quale versione di bash; ad esempio, i vecchi bash (come quelli che hanno spesso Solaris) potrebbero non includere queste nuove funzionalità bash. (Ho riscontrato questo problema esatto (corrispondenza del modello bash non implementata) su solaris w / bash 2.0)
michael

2
echoè insostituibile, dovresti printf '%s' "$haystackinvece utilizzare .
nyuszika7h,

2
No, evita del echotutto per tutto tranne che il testo letterale senza fughe che non inizia con a -. Potrebbe funzionare per te, ma non è portatile. Anche bash echosi comporterà in modo diverso a seconda che l' xpg_echoopzione sia impostata. PS: ho dimenticato di chiudere la doppia citazione nel mio commento precedente.
nyuszika7h,

1
@kevinarpe Non ne sono sicuro, --non è elencato nelle specifiche POSIX perprintf , ma dovresti printf '%s' "$anything"comunque usare , per evitare problemi se $anythingcontiene un %personaggio.
nyuszika7h,

1
@kevinarpe Sulla base di ciò, probabilmente lo è.
nyuszika7h,

21

Bash 4+ esempi. Nota: il non utilizzo delle virgolette causerà problemi quando le parole contengono spazi, ecc. Citate sempre in Bash, IMO.

Ecco alcuni esempi di Bash 4+:

Esempio 1, controlla 'yes' nella stringa (senza distinzione tra maiuscole e minuscole):

    if [[ "${str,,}" == *"yes"* ]] ;then

Esempio 2, controlla "yes" nella stringa (senza distinzione tra maiuscole e minuscole):

    if [[ "$(echo "$str" | tr '[:upper:]' '[:lower:]')" == *"yes"* ]] ;then

Esempio 3, controlla 'yes' nella stringa (case sensitive):

     if [[ "${str}" == *"yes"* ]] ;then

Esempio 4, controlla 'yes' nella stringa (case sensitive):

     if [[ "${str}" =~ "yes" ]] ;then

Esempio 5, corrispondenza esatta (maiuscole e minuscole):

     if [[ "${str}" == "yes" ]] ;then

Esempio 6, corrispondenza esatta (senza distinzione tra maiuscole e minuscole):

     if [[ "${str,,}" == "yes" ]] ;then

Esempio 7, corrispondenza esatta:

     if [ "$a" = "$b" ] ;then

Esempio 8, corrispondenza jolly .ext (senza distinzione tra maiuscole e minuscole):

     if echo "$a" | egrep -iq "\.(mp[3-4]|txt|css|jpg|png)" ; then

Godere.


17

Cosa ne pensi di questo:

text="   <tag>bmnmn</tag>  "
if [[ "$text" =~ "<tag>" ]]; then
   echo "matched"
else
   echo "not matched"
fi

2
= ~ è per la corrispondenza di regexp, quindi troppo potente per lo scopo del PO.

16

Come Paul ha menzionato nel suo confronto delle prestazioni:

if echo "abcdefg" | grep -q "bcdef"; then
    echo "String contains is true."
else
    echo "String contains is not true."
fi

Questo è conforme a POSIX come 'case "$ string" nella' risposta fornita da Marcus , ma è leggermente più facile da leggere rispetto alla risposta dell'istruzione case. Si noti inoltre che questo sarà molto più lento rispetto all'utilizzo di un'istruzione case. Come ha sottolineato Paul, non usarlo in un ciclo.



9
[[ $string == *foo* ]] && echo "It's there" || echo "Couldn't find"

Aggiungerò che l' echo "Couldn't findistruzione alla fine è un bel trucco per restituire 0 stati di uscita per questi comandi corrispondenti.
Nicodjimenez,

@nicodjimenez non puoi più scegliere come target lo stato di uscita con questa soluzione. Lo stato di uscita viene
assorbito

1
Questo è esattamente ciò che intendevo ... Se non lo || echo "Couldn't find"hai, restituirai uno stato di uscita dell'errore se non c'è corrispondenza, che potresti non voler se stai eseguendo una pipeline CI, ad esempio dove vuoi che tutti i comandi ritornino stati di uscita senza errori
nicodjimenez,

9

Uno è:

[ $(expr $mystring : ".*${search}.*") -ne 0 ] && echo 'yes' ||  echo 'no'

2
exprè una di quelle utility per coltelli svizzeri che di solito possono fare qualsiasi cosa tu debba fare, una volta che hai capito come farlo, ma una volta implementato, non puoi mai ricordare perché o come sta facendo quello che sta facendo, quindi tu non toccarlo mai più e spero che non smetta mai di fare quello che sta facendo.
michael

@AloisMahdal Non ho mai votato verso il basso, sto solo postulando sul perché sono stati dati i voti negativi. Un commento cautelativo. Uso expr, in rare occasioni, quando la portabilità impedisce l'uso di bash (es. Comportamento incoerente nelle versioni precedenti), tr (incoerente ovunque) o sed (a volte troppo lento). Ma per esperienza personale, ogni volta che rileggo questiexpr rileggo -ismi, devo tornare alla pagina man. Quindi, vorrei solo commentare che ogni uso di expressere commentato ...
michael

1
C'è stato un tempo in cui tutto ciò che avevi era la shell Bourne originale. Mancava alcune funzionalità comunemente richieste, quindi strumenti come expre testsono stati implementati per eseguirli. Al giorno d'oggi, di solito ci sono strumenti migliori, molti dei quali integrati in qualsiasi shell moderno. Immagino che testsia ancora lì, ma nessuno sembra mancare expr.
tripla il

6

Mi piace sed.

substr="foo"
nonsub="$(echo "$string" | sed "s/$substr//")"
hassub=0 ; [ "$string" != "$nonsub" ] && hassub=1

Modifica, logica:

  • Utilizzare sed per rimuovere l'istanza di sottostringa dalla stringa

  • Se la nuova stringa differisce dalla vecchia stringa, esiste una sottostringa


2
Per favore, aggiungi qualche spiegazione. Impartire la logica di base è più importante che dare semplicemente il codice, perché aiuta l'OP e altri lettori a risolvere da soli questo e simili problemi
Zulan

5

grep -q è utile per questo scopo.

Lo stesso usando awk:

string="unix-bash 2389"
character="@"
printf '%s' "$string" | awk -vc="$character" '{ if (gsub(c, "")) { print "Found" } else { print "Not Found" } }'

Produzione:

Non trovato

string="unix-bash 2389"
character="-"
printf '%s' "$string" | awk -vc="$character" '{ if (gsub(c, "")) { print "Found" } else { print "Not Found" } }'

Produzione:

Trovato

Fonte originale: http://unstableme.blogspot.com/2008/06/bash-search-letter-in-string-awk.html


3
echoè insostituibile, dovresti printf '%s' "$string"invece utilizzare . Sto modificando la risposta perché l'utente non sembra più esistere.
nyuszika7h,

In che modo echonon è portatile, @ nyuszika7h?
starbeamrainbowlabs

5

Ho scoperto di aver bisogno di questa funzionalità abbastanza frequentemente, quindi sto usando una funzione di shell fatta in casa .bashrccome questa che mi permette di riutilizzarla tutte le volte che ho bisogno, con un nome facile da ricordare:

function stringinstring()
{
    case "$2" in
       *"$1"*)
          return 0
       ;;
    esac
    return 1
}

Per verificare se $string1(diciamo, abc ) è contenuto in $string2(diciamo, 123abcABC ) ho solo bisogno di correre stringinstring "$string1" "$string2"e verificare il valore di ritorno, ad esempio

stringinstring "$str1" "$str2"  &&  echo YES  ||  echo NO

[["$ str" == $ substr ]] && echo YES || echo NO
elyase l'

Sono abbastanza sicuro che l' xhacking sia richiesto solo per shell molto vecchie.
nyuszika7h,

5

Il mio file .bash_profile e come ho usato grep:

Se la variabile di ambiente PATH include le mie due bindirectory, non aggiungerle,

# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

U=~/.local.bin:~/bin

if ! echo "$PATH" | grep -q "home"; then
    export PATH=$PATH:${U}
fi

1
Questa è una risposta?
codeforester

upvote. perché preoccuparsi di imparare come fa Bash quando grep, molto più potente, sarà probabilmente disponibile. estendere anche un po 'più lontano dalla corrispondenza con un elenco di modelli: grep -q -E 'pattern1|...|patternN'.
Mohamed Bana,

4

Estensione della domanda con risposta qui Come si fa a sapere se una stringa contiene un'altra stringa in POSIX sh?:

Questa soluzione funziona con caratteri speciali:

# contains(string, substring)
#
# Returns 0 if the specified string contains the specified substring,
# otherwise returns 1.
contains() {
    string="$1"
    substring="$2"

    if echo "$string" | $(type -p ggrep grep | head -1) -F -- "$substring" >/dev/null; then
        return 0    # $substring is in $string
    else
        return 1    # $substring is not in $string
    fi
}

contains "abcd" "e" || echo "abcd does not contain e"
contains "abcd" "ab" && echo "abcd contains ab"
contains "abcd" "bc" && echo "abcd contains bc"
contains "abcd" "cd" && echo "abcd contains cd"
contains "abcd" "abcd" && echo "abcd contains abcd"
contains "" "" && echo "empty string contains empty string"
contains "a" "" && echo "a contains empty string"
contains "" "a" || echo "empty string does not contain a"
contains "abcd efgh" "cd ef" && echo "abcd efgh contains cd ef"
contains "abcd efgh" " " && echo "abcd efgh contains a space"

contains "abcd [efg] hij" "[efg]" && echo "abcd [efg] hij contains [efg]"
contains "abcd [efg] hij" "[effg]" || echo "abcd [efg] hij does not contain [effg]"

contains "abcd *efg* hij" "*efg*" && echo "abcd *efg* hij contains *efg*"
contains "abcd *efg* hij" "d *efg* h" && echo "abcd *efg* hij contains d *efg* h"
contains "abcd *efg* hij" "*effg*" || echo "abcd *efg* hij does not contain *effg*"

Il test contains "-n" "n"non funziona qui, perché echo -ninghiottirà l' -nopzione come opzione! Una soluzione popolare per questo è quella di utilizzare printf "%s\n" "$string"invece.
joeytwiddle,

stringa perfettamente contenuta conteneva spazi
dengApro

4

Poiché la domanda POSIX / BusyBox è chiusa senza fornire la risposta corretta (IMHO), posterò una risposta qui.

La risposta più breve possibile è:

[ ${_string_##*$_substring_*} ] || echo Substring found!

o

[ "${_string_##*$_substring_*}" ] || echo 'Substring found!'

Nota che il doppio hash è obbligatorio con alcune shell ( ash). Sopra valuterà [ stringvalue ]quando la sottostringa non viene trovata. Non restituisce alcun errore. Quando viene trovata la sottostringa, il risultato è vuoto e viene valutato [ ]. Questo genererà il codice di errore 1 poiché la stringa è completamente sostituita (a causa di* ).

La sintassi più breve più comune:

[ -z "${_string_##*$_substring_*}" ] && echo 'Substring found!'

o

[ -n "${_string_##*$_substring_*}" ] || echo 'Substring found!'

Un altro:

[ "${_string_##$_substring_}" != "$_string_" ] && echo 'Substring found!'

o

[ "${_string_##$_substring_}" = "$_string_" ] || echo 'Substring found!'

Nota il segno di uguale singolo !


3

Corrispondenza esatta della parola:

string='My long string'
exactSearch='long'

if grep -E -q "\b${exactSearch}\b" <<<${string} >/dev/null 2>&1
  then
    echo "It's there"
  fi

3

Prova oobash.

È una libreria di stringhe in stile OO per Bash 4. Ha il supporto per le umlaut tedesche. È scritto in Bash.

Molte funzioni sono disponibili: -base64Decode, -base64Encode, -capitalize, -center, -charAt, -concat, -contains, -count, -endsWith, -equals, -equalsIgnoreCase, -reverse, -hashCode, -indexOf, -isAlnum, -isAlpha, -isAscii, -isDigit, -isEmpty, -isHexDigit, -isLowerCase, -isSpace, -isPrintable, -isUpperCase, -isVisible, -lastIndexOf, -length, -matches, -replaceAll, -replaceFirst, -startsWith, -substring, -swapCase, -toLowerCase, -toString, -toUpperCase, -trim, e -zfill.

Guarda l' esempio contiene :

[Desktop]$ String a testXccc
[Desktop]$ a.contains tX
true
[Desktop]$ a.contains XtX
false

oobash è disponibile su Sourceforge.net .


2

Uso questa funzione (una dipendenza non inclusa ma ovvia). Supera i test mostrati di seguito. Se la funzione restituisce un valore> 0, la stringa è stata trovata. È possibile restituire altrettanto facilmente 1 o 0.

function str_instr {
   # Return position of ```str``` within ```string```.
   # >>> str_instr "str" "string"
   # str: String to search for.
   # string: String to search.
   typeset str string x
   # Behavior here is not the same in bash vs ksh unless we escape special characters.
   str="$(str_escape_special_characters "${1}")"
   string="${2}"
   x="${string%%$str*}"
   if [[ "${x}" != "${string}" ]]; then
      echo "${#x} + 1" | bc -l
   else
      echo 0
   fi
}

function test_str_instr {
   str_instr "(" "'foo@host (dev,web)'" | assert_eq 11
   str_instr ")" "'foo@host (dev,web)'" | assert_eq 19
   str_instr "[" "'foo@host [dev,web]'" | assert_eq 11
   str_instr "]" "'foo@host [dev,web]'" | assert_eq 19
   str_instr "a" "abc" | assert_eq 1
   str_instr "z" "abc" | assert_eq 0
   str_instr "Eggs" "Green Eggs And Ham" | assert_eq 7
   str_instr "a" "" | assert_eq 0
   str_instr "" "" | assert_eq 0
   str_instr " " "Green Eggs" | assert_eq 6
   str_instr " " " Green "  | assert_eq 1
}

La suspense! Qual è la dipendenza?
Peter Mortensen,

La funzione "str_escape_special_characters". È nel file arcshell_str.sh di GitHub. arcshell.io ti porterà lì.
Ethan Post


0
msg="message"

function check {
    echo $msg | egrep [abc] 1> /dev/null

    if [ $? -ne 1 ];
    then 
        echo "found" 
    else 
        echo "not found" 
    fi
}

check

Questo troverà qualsiasi occorrenza di a o b o c


0

L' esempio generico del pagliaio dell'ago sta seguendo con le variabili

#!/bin/bash

needle="a_needle"
haystack="a_needle another_needle a_third_needle"
if [[ $haystack == *"$needle"* ]]; then
    echo "needle found"
else
    echo "needle NOT found"
fi
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.