En bash, ¿cómo puedo verificar si una cadena comienza con algún valor?

Me gustaría comprobar si una cadena comienza con “nodo”, por ejemplo, “node001”. Algo como

if [ $HOST == user* ] then echo yes fi 

¿Cómo puedo hacerlo correctamente?


Además, necesito combinar expresiones para verificar si HOST es “usuario1” o comienza con “nodo”

 if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ]; then echo yes fi > > > -bash: [: too many arguments 

¿Cómo hacerlo correctamente?

Este fragmento en la Guía de scripts avanzados de Bash dice:

 # The == comparison operator behaves differently within a double-brackets # test than within single brackets. [[ $a == z* ]] # True if $a starts with a "z" (wildcard matching). [[ $a == "z*" ]] # True if $a is equal to z* (literal matching). 

Entonces lo tenías casi correcto; necesitabas corchetes dobles , no corchetes individuales.


Con respecto a su segunda pregunta, puede escribirla de esta manera:

 HOST=user1 if [[ $HOST == user1 ]] || [[ $HOST == node* ]] ; then echo yes1 fi HOST=node001 if [[ $HOST == user1 ]] || [[ $HOST == node* ]] ; then echo yes2 fi 

Que hará eco

 yes1 yes2 

Bash’s if syntax es difícil de acostumbrarse (IMO).

Si está utilizando un bash reciente (v3 +), sugiera el operador de comparación bash regex =~ , es decir,

 if [[ "$HOST" =~ ^user.* ]]; then echo "yes" fi 

Para hacer coincidir this or that en un uso de expresiones regulares | , es decir,

 if [[ "$HOST" =~ ^user.*|^host1 ]]; then echo "yes" fi 

Nota: esta es la syntax de expresión regular “propia”.

  • user* significa use y cero o más apariciones de r , por lo que el use y userrrr coincidirán.
  • user.* significa el user y cero o más ocurrencias de cualquier carácter, por lo que el userX , el userX coincidirá.
  • ^user.* significa que coincide con el user.* del patrón user.* al comienzo de $ HOST.

Si no está familiarizado con la syntax de expresiones regulares, intente consultar este recurso .

Nota: es mejor si hace cada nueva pregunta como una nueva pregunta, hace que stackoverflow sea más ordenado y más útil. Siempre puede incluir un enlace a una pregunta anterior para referencia.

Siempre trato de seguir con POSIX sh en lugar de utilizar extensiones bash, ya que uno de los puntos principales de scripting es la portabilidad. (Además de conectar progtwigs, no reemplazarlos)

En sh, hay una manera fácil de verificar si hay una condición de “is-prefix”.

 case $HOST in node*) your code here esac 

Dado lo viejo, arcano y difícil que es (y bash no es la cura: es más complicado, menos consistente y menos portátil), me gustaría señalar un aspecto funcional muy agradable: mientras que algunos elementos de syntax como el case se construyen- en, las construcciones resultantes no son diferentes a cualquier otro trabajo. Se pueden componer de la misma manera:

 if case $HOST in node*) true;; *) false;; esac; then your code here fi 

O incluso más corto

 if case $HOST in node*) ;; *) false;; esac; then your code here fi 

O incluso más corto (solo para presentarlo como un elemento de idioma, pero ahora es un mal estilo)

 if ! case $HOST in node*) false;; esac; then your code here fi 

Si te gusta ser explícito, crea tu propio elemento de idioma:

 beginswith() { case $2 in "$1"*) true;; *) false;; esac; } 

¿No es esto realmente bastante agradable?

 if beginswith node "$HOST"; then your code here fi 

Y dado que sh es básicamente solo trabajos y listas de cadenas (y procesos internos, de los cuales están compuestos los trabajos), ahora podemos incluso hacer alguna progtwigción funcional liviana:

 beginswith() { case $2 in "$1"*) true;; *) false;; esac; } checkresult() { if [ $? = 0 ]; then echo TRUE; else echo FALSE; fi; } all() { test=$1; shift for i in "$@"; do $test "$i" || return done } all "beginswith x" x xy xyz ; checkresult # prints TRUE all "beginswith x" x xy abc ; checkresult # prints FALSE 

Esto es elegante No es que defienda usar sh para nada serio: se rompe demasiado rápido en los requisitos del mundo real (sin lambdas, por lo que debe usar strings. Pero las llamadas a funciones de anidamiento con strings no son posibles, los pipes no son posibles …)

Puede seleccionar solo la parte de la cadena que desea verificar:

 if [ ${HOST:0:4} = user ] 

Para su pregunta de seguimiento, puede usar un OR :

 if [[ $HOST == user1 || $HOST == node* ]] 

Prefiero los otros métodos ya publicados, pero a algunas personas les gusta usar:

 case "$HOST" in user1|node*) echo "yes";; *) echo "no";; esac 

Editar:

He agregado sus alternativas a la statement del caso anterior

En su versión editada tiene demasiados corchetes. Debe tener un aspecto como este:

 if [[ $HOST == user1 || $HOST == node* ]]; 

ya que # tiene un significado en bash, llegué a la siguiente solución.
Además, me gusta más empacar cadenas con “” para superar espacios, etc.

 A="#sdfs" if [[ "$A" == "#"* ]];then echo "skip comment line" fi 

Si bien la mayoría de las respuestas aquí son correctas, muchas contienen bashismos innecesarios. La expansión del parámetro POSIX le brinda todo lo que necesita:

 [ "${host#user}" != "${host}" ] 

y

 [ "${host#node}" != "${host}" ] 

${var#expr} elimina el prefijo más pequeño que coincide con ${var} y lo devuelve. Por lo tanto, si ${host} no comienza con el user ( node ), ${host#user} ( ${host#node} ) es lo mismo que ${host} .

expr permite comodines fnmatch() , por lo tanto, ${host#node??} y amigos también funcionan.

@OP, para ambas preguntas puede usar case / esac

 string="node001" case "$string" in node*) echo "found";; * ) echo "no node";; esac 

segunda pregunta

 case "$HOST" in node*) echo "ok";; user) echo "ok";; esac case "$HOST" in node*|user) echo "ok";; esac 

O Bash 4.0

 case "$HOST" in user) ;& node*) echo "ok";; esac 
 if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ]; then echo yes fi 

no funciona, porque todos [ , [[ y prueba reconocen la misma gramática no recursiva. ver la sección EXPRESIONES CONDICIONALES en tu página bash man.

Como un lado, el SUSv3 dice

El comando condicional derivado de KornShell (corchete doble [[]] ) se eliminó de la descripción del lenguaje de comandos del shell en una propuesta temprana. Se plantearon objeciones de que el problema real es el uso indebido del comando de prueba ( [ ), y ponerlo en el caparazón es la forma incorrecta de solucionar el problema. En cambio, la documentación adecuada y una nueva palabra reservada shell ( ! ) Son suficientes.

Las pruebas que requieren múltiples operaciones de prueba se pueden realizar a nivel del shell utilizando invocaciones individuales del comando de prueba y los lógicos del shell, en lugar de utilizar el indicador de prueba propenso a error -o .

necesitarías escribirlo de esta manera, pero la prueba no lo admite:

 if [ $HOST == user1 -o $HOST == node* ]; then echo yes fi 

la prueba usa = para igualdad de cadenas, más importante aún no admite la coincidencia de patrones.

case / esac tiene un buen soporte para la coincidencia de patrones:

 case $HOST in user1|node*) echo yes ;; esac 

tiene el beneficio adicional de que no depende de bash, la syntax es portátil. de la especificación Single Unix, el lenguaje de comandos de Shell:

 case word in [(]pattern1) compound-list;; [[(]pattern[ | pattern] ... ) compound-list;;] ... [[(]pattern[ | pattern] ... ) compound-list] esac 

Añadiendo un poco más detalles de syntax a la respuesta de rango más alto de Mark Rushakoff.

La expresion

 $HOST == node* 

También se puede escribir como

 $HOST == "node"* 

El efecto es el mismo. Solo asegúrate de que el comodín esté fuera del texto citado. Si el comodín está dentro de las comillas, se interpretará literalmente (es decir, no como un comodín).

Otra cosa que puedes hacer es sacar lo que estás haciendo eco y pipe con inline cut -c 1-1