string - solo - sed linux




Come verificare se una stringa contiene una sottostringa in Bash (14)

Risposta compatibile

Poiché ci sono già molte risposte usando le funzionalità specifiche di Bash, c'è un modo di lavorare con shell con funzionalità più povere, come busybox :

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

In pratica, ciò 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 sotto bash , dash , 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 @EeroAtonton, ecco una versione della stessa demo, testata con le stesse shell:

myfunc() {
    reqsubstr="$1"
    shift
    string="[email protected]"
    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 sfuggire o raddoppiare le virgolette e / o doppie virgolette:

$ 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, naturalmente, bash :

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

È tutto gente!

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 potrebbe essere vuota, come indicato da @Sjlver, la funzione diventerebbe:

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

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

stringContain() { [ -z "${2##*$1*}" ] && { [ -z "$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

Ho una stringa in Bash:

string="My string"

Come posso testare se contiene un'altra stringa?

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

Dove ?? è il mio operatore sconosciuto. Uso echo e grep ?

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

Sembra un po 'goffo.


Bash4 + esempi. Nota: non usare le virgolette causerà problemi quando le parole contengono spazi ecc. Sempre citare in bash IMO.

Ecco alcuni esempi di BASH4 +:

Esempio 1, verificare la presenza di "sì" nella stringa (senza distinzione tra maiuscole e minuscole):

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

Esempio 2, selezionare "sì" nella stringa (senza distinzione tra maiuscole e minuscole):

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

Esempio 3, selezionare "sì" nella stringa (distinzione tra maiuscole e minuscole):

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

Esempio 4, verificare la presenza di "sì" nella stringa (distinzione tra maiuscole e minuscole):

     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

godere.


Corrispondenza esatta:

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

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

Cosa ne pensi di questo:

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

Ho trovato che ho bisogno di questa funzionalità abbastanza frequentemente, quindi sto usando una funzione di shell fatta in casa nel mio .bashrc come questo che mi permette di riutilizzarla tutte le volte che mi serve, con un nome facile da ricordare:

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

Per verificare se $string1 (ad esempio, abc ) è contenuto in $string2 (ad esempio, 123abcABC ), devo solo eseguire stringinstring "$string1" "$string2" e verificare il valore restituito, ad esempio

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

Io uso questa funzione (una dipendenza non inclusa ma ovvia). Supera le prove mostrate di seguito. Se la funzione restituisce un valore> 0, la stringa è stata trovata. Si potrebbe facilmente restituire 1 o 0 invece.

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 "(" "'[email protected] (dev,web)'" | assert_eq 11
   str_instr ")" "'[email protected] (dev,web)'" | assert_eq 19
   str_instr "[" "'[email protected] [dev,web]'" | assert_eq 11
   str_instr "]" "'[email protected] [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
}

Mi piace sed

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

Modifica, logica:

  • Usa sed per rimuovere l'istanza della sottostringa dalla stringa

  • Se la nuova stringa è diversa dalla vecchia stringa, esiste una sottostringa


My .bash_profile e come ho usato grep se il PATH includeva le mie 2 cartelle bin, 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

Prova Oobash è una libreria di stringhe in stile OO per bash 4. Ha il supporto per le dieresi tedesche. È scritto in bash. Sono disponibili molte funzioni: -base64Decode , -base64Encode , -center , -charAt , -concat , -count , -endsWith , -equals , -equalsIgnoreCase , -reverse , -hashCode , -indexOf , -isAlnum , -isAlnum , -isAlnum , -isAlpha , -isAscii , -isDigit , -isEmpty , -isAlpha , -isAscii , -isDigit , -isEmpty , -isHexDigit , -isLowerCase , -isSpace , -isPrintable , -isUpperCase , -isVisible , -lastIndexOf , -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 .


Puoi utilizzare la risposta di Marcus (* caratteri jolly) anche all'esterno 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 posizionati tra virgolette doppie e i caratteri jolly * devono essere all'esterno.


Quindi ci sono molte soluzioni utili alla domanda - ma quale è la più veloce / usa la minima risorsa?

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'

Sostituire TEST ogni volta:

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

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

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

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

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

(doContain era nella risposta di F. Houri)

E per le risate:

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

Quindi, la semplice opzione di sostituzioni vince in modo prevedibile sia in un test esteso che in un caso. Il caso è portatile.

Piping out to 100000 greps è prevedibilmente doloroso! La vecchia regola sull'utilizzo di utilità esterne senza necessità è vera.


Se preferisci l'approccio regex:

string='My string';

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

grep -q è utile per questo scopo.

Lo stesso con 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


Questa risposta di overflow dello stack era l'unica a intrappolare i caratteri di spazio e di trattino:

# For null cmd arguments checking   
to_check=' -t'
space_n_dash_chars=' -'
[[ $to_check == *"$space_n_dash_chars"* ]] && echo found




substring