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