GNU/Linux >> Tutoriales Linux >  >> Linux

¿Shell prueba si la cadena de varias líneas contiene un patrón especificado en la última línea?

Quiero determinar si una cadena de varias líneas termina con una línea que contiene un patrón específico.

Este código falló, no coincide.

s=`echo hello && echo world && echo OK`
[[ "$s" =~ 'OK$' ]] && echo match

Respuesta aceptada:

En bash 3.2 o superior y si la compatibilidad con 3.1 no está habilitada (con el compat31 opción o BASH_COMPAT=3.1 ), citando operadores de expresiones regulares (no solo con pero con cualquiera de los bash operadores de comillas ('...' , "..." , $'...' , $"..." )) elimina su significado especial.

[[ $var =~ 'OK$' ]]

coincide solo en cadenas que contienen OK$ literalmente (que $ coincide con un literal $ )

[[ $var =~ OK$ ]]

coincidencias en cadenas que terminan en OK (que $ es el operador RE que coincide al final de la cadena).

Eso también se aplica a las expresiones regulares almacenadas en variables o el resultado de alguna sustitución.

[[ $var =~ $regexp ]]   # $var matches $regexp
[[ $var =~ "$string" ]] # $var contains $string

Tenga en cuenta que puede volverse incómodo porque hay algunos caracteres que debe citar para la sintaxis de shell (como espacios en blanco, < , > , & , paréntesis cuando no coincide). Por ejemplo, si desea hacer coincidir con el .{3} <> [)}]& expresión regular (3 caracteres seguidos de un " <> " , ya sea un ) o } y un & ), necesitas algo como:

[[ $var =~ .{3}" <> "[})]& ]]

Si tiene dudas sobre qué caracteres necesitan citarse, siempre puede usar una variable temporal. Eso también significa que hará que el código sea compatible con bash31 , zsh o ksh93 :

pattern='.{3} <> [})]&'
[[ $var =~ $pattern ]] # remember *not* to quote $pattern here

Esa es también la única forma (aparte de usar el compat31 opción (o BASH_COMPAT=3.1 )) puede hacer uso de los operadores extendidos no POSIX de las expresiones regulares de su sistema.

Por ejemplo, para < para ser tratado como el límite de palabras que es en muchos motores de expresiones regulares, necesita:

pattern='<word>'
[[ $var =~ $pattern ]]

Haciendo:

[[ $var =~ <word> ]]

no funcionará como bash trata a esos como operadores de comillas de shell y eliminarlos antes de pasar <word> a la biblioteca de expresiones regulares.

Tenga en cuenta que es mucho peor en ksh93 donde:

[[ $var =~ "x.*$" ]]

por ejemplo, coincidirá con whatever-xa* pero no whatever-xfoo . La cita anterior elimina el significado especial de * , pero no a . ni $ .

El zsh el comportamiento es más simple:citar no cambia el significado de los operadores de expresiones regulares allí (como en bash31), lo que hace que el comportamiento sea más predecible (también puede usar expresiones regulares de PCRE en lugar de ERE (con set -o rematchpcre )).

Relacionado:¿Opción del menú contextual de Nautilus para crear un nuevo archivo?

yash no tiene un [[...]] construir, pero es [ incorporado tiene un =~ operador (también en zsh ). Y por supuesto, [ siendo un comando normal, las comillas no pueden afectar la forma en que se interpretan los operadores de expresiones regulares.

También tenga en cuenta que estrictamente hablando, su $s no contiene 3 líneas, sino 2 líneas completas seguidas de una línea sin terminar. Contiene hellonworldnOK . En el OK$ expresión regular extendida, el $ el operador solo coincidiría al final de la cadena .

En una cadena de 3 líneas completas , como hellonworldnOKn (que no podría obtener con la sustitución de comandos, ya que la sustitución de comandos elimina todo caracteres finales de nueva línea), el $ coincidiría después de n , entonces OK$ no coincidiría con él.

Con zsh -o pcrematch sin embargo, el $ coincide tanto al final de la cadena como antes de la nueva línea al final de la cadena si hay una, ya que no pasa el PCRE_DOLLAR_ENDONLY marcar a pcre_compile . Eso podría verse como una mala idea ya que, por lo general, las variables en los shells no contienen un carácter de nueva línea final y, cuando lo hacen, generalmente queremos que se consideren como datos.


Linux
  1. Inserte varias líneas de datos en un archivo después de que el patrón coincida con el script de shell de Linux

  2. ¿Cómo eliminar las primeras/últimas líneas 'n' de la salida del comando en Shell?

  3. ¿Mantener solo la primera línea de cada secuencia de líneas consecutivas que coincidan con un patrón?

  4. ¿Cómo saber si una duración es superior a una hora en varios scripts de shell?

  5. ¿Cómo concatenar varias líneas de salida en una sola línea?

Cómo comentar varias líneas a la vez en Vim Editor

Cómo eliminar varias líneas en Vim

Cómo reemplazar una cadena en varios archivos en la línea de comando de Linux

Convertir varias líneas en una línea separada por comas

Inserte varias líneas en un archivo después del patrón especificado usando el script de shell

¿Cómo edito líneas anteriores en un comando de varias líneas en Bash?