Tengo una cadena en Bash:
string="My string"
¿Cómo puedo probar si contiene otra cadena?
if [ $string ?? 'foo' ]; then
echo "It's there!"
fi
¿Dónde ??
está mi operador desconocido? ¿Utilizo echo y grep
?
if echo "$string" | grep 'foo'; then
echo "It's there!"
fi
Eso se ve un poco torpe.
expr
comando aquíRespuestas:
También puede usar la respuesta de Marcus (* comodines) fuera de una declaración de caso, si usa corchetes dobles:
Tenga en cuenta que los espacios en la cadena de la aguja deben colocarse entre comillas dobles, y los
*
comodines deben estar afuera. También tenga en cuenta que se utiliza un operador de comparación simple (es decir==
), no el operador de expresiones regulares=~
.fuente
#!/bin/sh
. Intenta en su#!/bin/bash
lugar.[[
. Ver ideone.com/ZSy1gZSi prefiere el enfoque regex:
fuente
=~
operador ya busca en toda la cadena una coincidencia; los.*
's aquí son extraños. Además, las citas son generalmente preferibles a las barras invertidas:[[ $string =~ "My s" ]]
E14)
. Probablemente sea mejor asignar a una variable (usando comillas), luego comparar. Así:re="My s"; if [[ $string =~ $re ]]
if [[ ! "abc" =~ "d" ]]
es verdadero.number=2; if [[ "1, 2, 4, 5" = *${number}* ]]; then echo forward $number; fi; if [[ *${number}* = "1, 2, 4, 5" ]]; then echo backwards $number; fi;
No estoy seguro de usar una declaración if, pero puede obtener un efecto similar con una declaración de caso:
fuente
[[ $string == *foo* ]]
también funciona en algunas versiones sh compatibles con POSIX (por ejemplo,/usr/xpg4/bin/sh
en Solaris 10) y ksh (> = 88)[[
... ¡el interruptor de la caja funcionó!stringContain
variantes (compatibles o independientes de mayúsculas y minúsculas)Como estas respuestas de desbordamiento de pila se refieren principalmente a Bash , he publicado una función Bash independiente del caso en la parte inferior de esta publicación ...
De todos modos, ahí está mi
Respuesta compatible
Como ya hay muchas respuestas usando las características específicas de Bash, hay una manera de trabajar bajo shells con características más pobres, como BusyBox :
En la práctica, esto podría dar:
Esto se probó en Bash, Dash , KornShell (
ksh
) y ash (BusyBox), y el resultado es siempre:En una función
Según lo solicitado por @EeroAaltonen, aquí hay una versión de la misma demostración, probada bajo los mismos shells:
Entonces:
Aviso: tiene que escapar o doble comillas y / o comillas dobles:
Función simple
Esto se probó en BusyBox, Dash y, por supuesto, Bash:
Entonces ahora:
... O si la cadena enviada pudiera estar vacía, como lo señaló @Sjlver, la función sería:
o como lo sugiere el comentario de Adrian Günter , evitando
-o
interruptores:Función final (simple):
E invirtiendo las pruebas para que sean potencialmente más rápidas:
Con cadenas vacías:
Caso independiente (¡solo Bash!)
Para probar cadenas sin cuidado de mayúsculas y minúsculas, simplemente convierta cada cadena a minúsculas:
Cheque:
fuente
string_contains() { [ -z "${2##*$1*}" ] && [ -n "$2" -o -z "$1" ]; }
Un pensamiento final: ¿la cadena vacía contiene la cadena vacía? La versión anterior dice sí (debido a la-o -z "$1"
parte).Debe recordar que las secuencias de comandos de shell son menos un lenguaje y más una colección de comandos. Instintivamente piensas que este "lenguaje" requiere que sigas a
if
con a[
o a[[
. Ambos son solo comandos que devuelven un estado de salida que indica éxito o fracaso (como cualquier otro comando). Por esa razón usaríagrep
, y no el[
comando.Solo haz:
Ahora que está pensando
if
en probar el estado de salida del comando que lo sigue (completo con punto y coma), ¿por qué no reconsiderar la fuente de la cadena que está probando?La
-q
opción hace que grep no muestre nada, ya que solo queremos el código de retorno.<<<
hace que el shell expanda la siguiente palabra y la use como entrada para el comando, una versión de una línea del<<
documento aquí (no estoy seguro de si esto es estándar o un Bashism).fuente
if grep -q foo <(echo somefoothing); then
echo
es portátil, si está pasando una variable, useprintf '%s' "$string
en su lugar.grep -q foo <<<"$mystring"
1 tenedor implícito y es bashism e implicaecho $mystring | grep -q foo
2 tenedores (uno para la tubería y el segundo para correr/path/to/grep
)echo
sin banderas aún podría tener problemas de portabilidad inesperados si la cadena de argumentos contiene secuencias de barra invertida.echo "nope\c"
se espera que en algunas plataformas funcione comoecho -e "nope"
en otras.printf '%s' "nope"
vsprintf '%s\n' 'nope\c'
La respuesta aceptada es la mejor, pero como hay más de una forma de hacerlo, aquí hay otra solución:
${var/search/replace}
es$var
con la primera instancia desearch
reemplazado porreplace
, si se encuentra (no cambia$var
). Si intenta reemplazarfoo
por nada, y la cadena ha cambiado, entonces obviamentefoo
se encontró.fuente
Entonces, hay muchas soluciones útiles para la pregunta, pero ¿cuál es la más rápida / usa la menor cantidad de recursos?
Pruebas repetidas usando este marco:
Reemplazar TEST cada vez:
(doContain estaba en la respuesta de F. Houri)
Y para las risas:
Por lo tanto, la opción de sustitución simple previsiblemente gana ya sea en una prueba extendida o en un caso. El estuche es portátil.
¡Contar con 100000 greps es previsiblemente doloroso! La antigua regla sobre el uso de utilidades externas sin necesidad es cierta.
fuente
[[ $b == *$a* ]]
.case
gana con el menor consumo de tiempo total. Sin$b in *$a
embargo, te falta un asterisco después . Obtengo resultados ligeramente más rápidos para[[ $b == *$a* ]]
quecase
con el error corregido, pero podría depender de otros factores también, por supuesto.[[ $b == *$a* ]]
es rápido ycase
es casi tan rápido (y agradablemente compatible con POSIX).Esto también funciona:
Y la prueba negativa es:
Supongo que este estilo es un poco más clásico, menos dependiente de las características del shell Bash.
El
--
argumento es pura paranoia POSIX, utilizada para proteger contra cadenas de entrada similares a las opciones, como--abc
o-a
.Nota: En un bucle cerrado, este código será mucho más lento que el uso de las funciones internas del shell Bash, ya que uno (o dos) procesos separados se crearán y conectarán a través de tuberías.
fuente
echo
no es portátil, deberías usarlo en suprintf '%s' "$haystack
lugar.echo
por completo cualquier cosa que no sea texto literal sin escapes que no comience con a-
. Puede funcionar para usted, pero no es portátil. Incluso bashecho
se comportará de manera diferente dependiendo de si laxpg_echo
opción está configurada. PD: Olvidé cerrar la comilla doble en mi comentario anterior.--
no aparece en la especificación POSIX paraprintf
, pero debe usar deprintf '%s' "$anything"
todos modos, para evitar problemas si$anything
contiene un%
carácter.Bash 4+ ejemplos. Nota: no usar comillas causará problemas cuando las palabras contengan espacios, etc. Comillas siempre en Bash, IMO.
Aquí hay algunos ejemplos de Bash 4+:
Ejemplo 1, verifique 'sí' en la cadena (sin distinción entre mayúsculas y minúsculas):
Ejemplo 2, verifique 'sí' en la cadena (sin distinción entre mayúsculas y minúsculas):
Ejemplo 3, verifique 'sí' en la cadena (distingue entre mayúsculas y minúsculas):
Ejemplo 4, verifique 'sí' en la cadena (distingue entre mayúsculas y minúsculas):
Ejemplo 5, coincidencia exacta (mayúsculas y minúsculas):
Ejemplo 6, coincidencia exacta (sin distinción entre mayúsculas y minúsculas):
Ejemplo 7, coincidencia exacta:
Ejemplo 8, coincidencia con comodines .ext (sin distinción entre mayúsculas y minúsculas):
Disfrutar.
fuente
Qué tal esto:
fuente
Como Paul mencionó en su comparación de rendimiento:
Esto es compatible con POSIX como el 'case "$ string" en' la respuesta proporcionada por Marcus , pero es un poco más fácil de leer que la respuesta de la declaración de caso. También tenga en cuenta que esto será mucho más lento que usar una declaración de caso. Como señaló Paul, no lo use en un bucle.
fuente
Esta respuesta de desbordamiento de pila fue la única que atrapó el espacio y los caracteres del guión:
fuente
fuente
echo "Couldn't find
declaración al final es un buen truco para devolver 0 estados de salida para estos comandos coincidentes.|| echo "Couldn't find"
, devolverá un estado de salida de error si no hay coincidencia, lo que puede que no desee si está ejecutando una canalización de CI, por ejemplo, donde desea que regresen todos los comandos estados de salida sin errorUno es:
fuente
expr
es una de esas utilidades de navaja suiza que generalmente puede hacer lo que sea que necesites hacer, una vez que descubres cómo hacerlo, pero una vez implementado, nunca puedes recordar por qué o cómo está haciendo lo que está haciendo, así que nunca lo toque de nuevo y espere que nunca deje de hacer lo que está haciendo.expr
, en raras ocasiones, cuando la portabilidad impide el uso de bash (por ejemplo, comportamiento inconsistente en versiones anteriores), tr (inconsistente en todas partes) o sed (a veces demasiado lento). Pero por experiencia personal, cada vez queexpr
releo estos ismos, tengo que volver a la página del manual. Por lo tanto, me acaba de comentar que cada uso deexpr
ser comentado ...expr
ytest
se implementaron para realizarlas. En la actualidad, generalmente hay mejores herramientas, muchas de ellas integradas en cualquier shell moderno. Supongotest
que todavía está ahí, pero parece que no falta nadieexpr
.Me gusta sed
Editar, Lógica:
Use sed para eliminar la instancia de la subcadena de la cadena
Si la nueva cadena difiere de la antigua, existe una subcadena
fuente
grep -q
Es útil para este propósito.Lo mismo usando
awk
:Salida:
Salida:
Fuente original: http://unstableme.blogspot.com/2008/06/bash-search-letter-in-string-awk.html
fuente
echo
no es portátil, deberías usarlo en suprintf '%s' "$string"
lugar. Estoy editando la respuesta porque el usuario ya no parece existir.echo
no es portátil, @ nyuszika7h?Descubrí que necesitaba esta funcionalidad con bastante frecuencia, por lo que estoy usando una función de shell casera en mi
.bashrc
estilo que me permite reutilizarla tantas veces como sea necesario, con un nombre fácil de recordar:Para probar si
$string1
(digamos, abc ) está contenido en$string2
(digamos, 123abcABC ) solo necesito ejecutarstringinstring "$string1" "$string2"
y verificar el valor de retorno, por ejemplofuente
x
truco solo es necesario para conchas muy antiguas.My .bash_profile archivo y cómo usé grep:
Si la variable de entorno PATH incluye mis dos
bin
directorios, no los agregue,fuente
grep -q -E 'pattern1|...|patternN'
.Extensión de la pregunta respondida aquí ¿Cómo saber si una cadena contiene otra cadena en POSIX sh? :
Esta solución funciona con caracteres especiales:
fuente
contains "-n" "n"
no funciona aquí, porqueecho -n
se tragará-n
como una opción! Una solución popular para eso es usarprintf "%s\n" "$string"
en su lugar.Desde el POSIX pregunta / BusyBox está cerrada sin proporcionar la respuesta correcta (en mi humilde opinión), publicaré una respuesta aquí.
La respuesta más corta posible es:
o
Tenga en cuenta que el doble hash es obligatorio con algunos shells (
ash
). Lo anterior evaluará[ stringvalue ]
cuando no se encuentre la subcadena. No devuelve ningún error. Cuando se encuentra la subcadena, el resultado está vacío y se evalúa[ ]
. Esto arrojará el código de error 1 ya que la cadena está completamente sustituida (debido a*
).La sintaxis más corta más común:
o
Otro:
o
Tenga en cuenta el signo igual único !
fuente
Concordancia exacta de palabras:
fuente
Prueba oobash.
Es una biblioteca de cadenas de estilo OO para Bash 4. Tiene soporte para diéresis alemanas. Está escrito en Bash.
Muchas de las funciones están disponibles:
-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
, y-zfill
.Mira el ejemplo contiene :
oobash está disponible en Sourceforge.net .
fuente
Yo uso esta función (una dependencia no incluida pero obvia). Pasa las pruebas que se muestran a continuación. Si la función devuelve un valor> 0, se encontró la cadena. Podría simplemente devolver 1 o 0 en su lugar.
fuente
Esta es la misma respuesta que https://stackoverflow.com/a/229585/11267590 . Pero estilo simple y también compatible con POSIX.
fuente
Esto encontrará cualquier ocurrencia de a o b o c
fuente
El ejemplo genérico de pajar de agujas está siguiendo con variables
fuente