¿Cómo hacer coincidir la cadena exacta con `sed`? Pero no la parte de eso.


8

Tengo un archivo de entrada FILE1.TXT como se muestra a continuación.


11 id1  
12  
13 AGE = 20  
14 NAME = NAME1  
15  
16 id2  
17  
18 AGE = 30  
19 NAME = NAME2  
.  
.  
.  
110 idXYZ  
111  
112 AGE = AGEXYZ  
113 NAME = NAMEXYZ  
114  
115 idZZZ  
116

Quiero buscar en todos los campos que pertenecen a un Id en particular y obtener el valor de NAME

Logré recorrer cada Id y formé el siguiente comando para cada Id según sea necesario.

sed -n '/11/,/14/p' FILE1.TXT | grep NAME | awk -F "= " '{print $2}'

El problema aquí es que obtengo la salida NAME1 , además de eso, también obtengo NAMEXYZ .

¿Qué se debe cambiar para que solo obtenga NAME1 pero no NAMEXYZ ?

Como solución alternativa, los siguientes comandos funcionan.

sed -n '/11/,/14/p' FILE1.TXT | grep NAME | awk -F "= " '{print $2}'|head -1

¿Hay algún 'interruptor' o me estoy perdiendo algo?

Respuestas:


3

Si conoce los números de línea que desea buscar (como sugiere su Q), ajuste la expresión regular para que no coincida con las líneas no deseadas.

Por ejemplo, cambiar:

sed -n '/11/,/14/p' | grep NAME | awk -F "= " '{print $2}'

a

sed -n '/^11 /,/^14 /p' | grep NAME | awk -F "= " '{print $2}'

El ^coincidirá con el comienzo de la línea y un espacio después de las garantías número que el número de línea específico será igualado, y no se procesará bloques no deseados.


Eso podría ayudar. Pero, ¿cómo puedo igualar ^(random no of spaces)11?
Vinay

1
@VinayChalluru usesed -n '/^\s*11 /,/^\s*14 /p'
casey

1
puede ser breve usando sed -n '/^11 /,/^14 /p' | awk '/NAME/{print $NF}' ¿has probado esto?
Rahul Patil

@RahulPatil Sí, funciona.
Vinay

6

Use límites de palabras:

grep '\bNAME1\b'

coincidiría NAME1y no NAME1XYZo XYZNAME1.

Similar,

sed -n '/11\b/,/14\b/p'

no coincidiría con las líneas que contienen 111y 142.


EDITAR: Parece que los números en el archivo de entrada son en realidad números de línea. Si ese es el caso, simplemente podría decir:

sed '11,14!d'

para obtener las líneas deseadas.


Solo hay uno NAMEentre las líneas 11 y 14. Entonces, ¿por qué está sedmirando 111y 114? ¿Cómo hacer que no se vea en el medio 111y 114?
Vinay

@VinayChalluru Vea la respuesta anterior para saber cómo podría modificar la sedexpresión.
devnull

Esto responde a mi pregunta, supongo. Déjame intentarlo y dejarte saber.
Vinay

para límites de palabras, grepcon -wbandera? no es asi
Rahul Patil

1
@RahulPatil Yup, para el ejemplo anterior -wsería equivalente. Por sedejemplo, -wes ligeramente diferente.
devnull

4

Puedes usar AWK

awk 'NR>=13 && NR<=17 && /NAME/{print $NF}' infile

Esto buscará líneas entre 13 y 17, luego buscará Nombre y, si coincide, imprimirá la última palabra de Name = LastWord


Cuando trato de hacer esto, aparece un error que dice que el número de línea de entrada debe ser menor que 199.
Vinay

@VinayChalluru, ¿puede mostrarme la salida con el comando? Utilice paste.ubuntu.com
Rahul Patil,

Disculpas Agregué un $antes NRy eso causó el error.
Vinay

@VinayChalluru Está bien. eso es bueno, probaste / probaste cada ans y aprendiste algo nuevo ..: D
Rahul Patil

Exactamente. Hay mucho más por delante. :-)
Vinay

4

No necesita ninguna otra herramienta para esto, sedlo manejará fácilmente por completo.

sed -nr '/11/,/14/{s/^.*NAME =\s*(\S*).*$/\1/p}' <$infile

Eso debería proporcionarle solo la primera secuencia de caracteres que no sean espacios en blanco después de la frase "NAME =" para cada línea en la que se encuentra esa frase entre las líneas 11 y 14 de cualquier archivo de entrada sed.


3

sed no es la herramienta adecuada para este trabajo. Use awk donde puede especificar la identificación que está buscando e imprima el siguiente NOMBRE que aparece.

awk -v id="id2" '
    $NF == id {have_id = 1} 
    have_id && $0 ~ /NAME/ {print $NF; exit}
' filename

¿Podría explicar las líneas dos y tres de su comando awk?
erik

0

versión genérica no basada en el número de línea sino en la referencia de identificación

sed -n '1h;1!H;
$ {
  x
  s/.*/&\^J/
: clean
#  put your ID pattern here in place of id9
  s/.*\(id9 *\n.*\)id[0-9]\{1,\} *\n.*/\1/
  t clean
  s/.*NAME = \([^[:cntrl:]]*\)\n.*/\1/
  p
  }' YourFile
  1. cargar todo el archivo
  2. la sección limpia no forma parte del grupo de identificación (recursiva)
  3. solo tome el valor de contenido de NAME en el grupo
  4. imprimir el resultado

0

Puede imprimir las líneas que contienen patrones coincidentes utilizando sed de la siguiente manera:

sed -n '/pattern/p'  Filename
  • -n- estas opciones desactivan esta impresión automática, y sed solo produce resultados cuando se le indica explícitamente a través del pcomando.

  • p - impresión

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.