string - paso - scripts linux ejercicios resueltos
En bash, ¿cómo puedo verificar si una cadena comienza con algún valor? (11)
@OP, para tus dos preguntas puedes 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
Me gustaría comprobar si una cadena comienza con "node", por ejemplo, "node001". Algo como
if [ $HOST == user* ]
then
echo yes
fi
¿Cómo puedo hacerlo correctamente?
Además, necesito combinar expresiones para comprobar 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?
Agregando un poco más de detalle de sintaxis 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úrese 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).
Este fragmento de la Guía avanzada de scripts 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).
Así que lo tenías casi correcto; necesitabas corchetes dobles , no corchetes simples.
Con respecto a tu segunda pregunta, puedes 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 es if
es difícil acostumbrarse a la sintaxis (IMO).
Otra cosa que puede hacer es descartar lo que está haciendo eco y canalizar con inline cut -c 1-1
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 declaración del caso anterior
En tu versión editada tienes demasiados paréntesis. Debe tener un aspecto como este:
if [[ $HOST == user1 || $HOST == node* ]];
Puede seleccionar solo la parte de la cadena que desea verificar:
if [ ${HOST:0:4} = user ]
Para su pregunta de seguimiento, puede utilizar un OR :
if [[ $HOST == user1 || $HOST == node* ]]
Si bien aquí la mayoría de las respuestas son bastante correctas, muchas de ellas contienen bashismos innecesarios. La expansión de parámetros POSIX le ofrece todo lo que necesita:
[ "${host#user}" != "${host}" ]
y
[ "${host#node}" != "${host}" ]
${var#expr}
elimina el prefijo más pequeño que coincide con expr
de ${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 fnmatch()
comodines, por lo que ${host#node??}
y amigos también funcionan.
Si está utilizando un reciente bash (v3 +), sugiera el operador de comparación bash regex =~
, es decir,
if [[ "$HOST" =~ ^user.* ]]; then
echo "yes"
fi
Para igualar this or that
en una expresión regular use |
es decir
if [[ "$HOST" =~ ^user.*|^host1 ]]; then
echo "yes"
fi
Nota: esta es la sintaxis de expresión regular "correcta".
-
user*
significause
y cero o más apariciones der
, por lo queuse
yuserrrr
coincidirán. -
user.*
significauser
y cero o más ocurrencias de cualquier carácter, por lo queuserX
,userX
coincidirá. -
^user.*
significa que coincida con el patrón deuser.*
al comienzo de $ HOST.
Si no está familiarizado con la sintaxis de expresiones regulares, intente consultar este recurso .
Nota: es mejor si hace cada nueva pregunta como una nueva pregunta, hace que sea más ordenado y más útil. Siempre puede incluir un enlace a una pregunta anterior como referencia.
Siempre trato de mantener POSIX sh en lugar de usar las extensiones de bash, ya que uno de los puntos principales de las secuencias de comandos es la portabilidad. (Además de conectar programas, no reemplazarlos)
En sh, hay una manera fácil de verificar una condición "es-prefijo".
case $HOST in node*)
your code here
esac
Teniendo en cuenta la antigüedad, arcano y crufty sh (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 sintaxis como el case
están integrados 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 presentar !
Como elemento del idioma, pero ahora es un estilo malo)
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 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 se componen los trabajos), ahora podemos hacer algo de programación funcional ligera:
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 abogue por usar sh para nada serio, se rompe demasiado rápido en los requisitos del mundo real (no lambdas, por lo que debe usar cadenas. Pero no es posible realizar llamadas de función de anidación con cadenas, no es posible usar tuberías ...)
ya que # tiene un significado en bash llegué a la siguiente solución.
Además, me gusta más empaquetar cuerdas con "" para superar espacios, etc.
A="#sdfs"
if [[ "$A" == "#"* ]];then
echo "skip comment line"
fi
if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];
then
echo yes
fi
no funciona, porque todos [ , [[ y la prueba reconocen la misma gramática no recurrente. Consulte la sección EXPRESIONES CONDICIONALES en su página de manual de bash.
Como un aparte, el SUSv3 dice
El comando condicional derivado de KornShell (doble corchete [[]] ) se eliminó de la descripción del lenguaje del comando de shell en una propuesta inicial. Se plantearon objeciones de que el problema real es el uso incorrecto del comando de prueba ( [ ), y ponerlo en el shell es la forma incorrecta de solucionar el problema. En su lugar, la documentación adecuada y una nueva palabra de shell reservada ( ! ) Son suficientes.
Las pruebas que requieren múltiples operaciones de prueba se pueden realizar a nivel de shell utilizando invocaciones individuales del comando de prueba y las lógicas de shell, en lugar de usar el indicador de prueba propenso a errores.
necesitarías escribirlo de esta manera, pero la prueba no lo admite:
if [ $HOST == user1 -o $HOST == node* ];
then
echo yes
fi
prueba usa = para la igualdad de cadenas, lo más importante es que 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 sintaxis es portátil. de la Especificación Unix única, el lenguaje de comandos de shell:
case word in
[(]pattern1) compound-list;;
[[(]pattern[ | pattern] ... ) compound-list;;] ...
[[(]pattern[ | pattern] ... ) compound-list]
esac