Extraiga una parte de una línea de un archivo con sed

18

Quiero leer una parte de una línea de un archivo. Por ejemplo:

POP3_SERVER_NAME = localhost

Solo quiero volver localhost, usando sed.

Este texto está en la tercera línea. Hago esto para extraer la línea:

sed -n '3p' installation.sh

¿Cómo extraigo solo la localhostparte?

Mercer
fuente

Respuestas:

26

awk podría ser una mejor herramienta aquí.

$ cat test.dat
LINE 1
LINE 2
POP3_SERVER_NAME = localhost

Busque líneas que contengan "POP3_SERVER_NAME"; imprime el último campo. Esto no depende de que POP3_SERVER_NAME esté siempre en la línea 3, lo que probablemente sea algo bueno.

$ awk '/POP3_SERVER_NAME/{print $NF}' test.dat
localhost

Dependiendo de su aplicación, es posible que deba hacer que la expresión regular sea más estricta. Por ejemplo, es posible que desee hacer coincidir solo esa línea que comienza con POP3_SERVER_NAME.

$ awk '/^POP3_SERVER_NAME/{print $NF}' test.dat
localhost

Usar sed es un poco menos intuitivo. (Gracias, soy consciente de la ironía). Dirija la línea que contiene POP3_SERVER_NAME en cualquier lugar. Sustituya una cadena vacía por todo el texto desde el comienzo de la línea hasta el espacio opcional que sigue a "=". Luego imprime.

sed -n -e '/POP3_SERVER_NAME/ s/.*\= *//p' test.dat
Mike Sherrill 'Retiro del gato'
fuente
2
El awkcomando es bueno, pero solo si tienes espacios alrededor del =. No funcionará para POP3_SERVER_NAME=localhost.
Marcel Stör
2
@ Marcel, puede cambiar el delimitador utilizado por awkde espacios a otra cosa utilizando -F. Por ejemplo: -F "="se usará =como delimitador en el caso que mencione.
mattpr
7

Reemplace el pcomando por una sustitución que elimine la parte no deseada de la línea.

sed -n '3 s/^[^=]*= *//p' installation.sh

Es posible que desee hacer coincidir la línea por palabra clave en lugar de por posición.

sed -n 's/^ *POP3_SERVER_NAME *= *//p' installation.sh
Gilles 'SO- deja de ser malvado'
fuente
6

Parece que tienes un archivo de configuración. Lo que podría hacer es similar a lo que sugiere Adam Siemeon / slm:

sed -nr 's/[^=]+=\s*(.+)$/\1/p' filename

donde [^=]excluye todos los '=' caracteres, +dice una o más del mismo tipo de carácter, este seguido por un real =, \scualquier espacio en blanco (incluyendo las lengüetas \ty las nuevas líneas \n, \r\ny espacios lisos '', mientras que *medios de cero o más del mismo tipo , los paréntesis capturan lo que hay dentro para colocar las secuencias de caracteres coincidentes en los marcadores de posición de reemplazo \ 1, \ 2, ..., \ n, $significa el final de una línea. Esto sigue el patrón de reemplazo típico de:. s/.../.../modifiersLa opción de línea de comando -rsignifica sintaxis de expresiones regulares extendida (por conveniencia) y -nsignifica que no se genera nada hasta que se solicite explícitamente o no. El pmodificador imprime el resultado.

Puede realizar una búsqueda global con el gmodificador como:

sed -nr 's/[^=]+=\s*(.+)$/\1 /pg' filename  # note the space after \1

de manera que se obtiene una cadena separada por ' '(podría ser \n, \to lo que sea) que se puede procesar fácilmente.

Ambos son válidos siempre que sus valores precedidos por el carácter de la ecuación se extiendan hasta el final de una línea y no sean seguidos por comentarios u otros caracteres cuya semántica se desvíe de un simple "valor".


Editar:

Todavía no puedo comentar aquí sobre las publicaciones de otros. Para indicar la línea, simplemente pase el número de línea, en su caso 3, antes so antes del inicio de la cotización (como en vim).

sed -nr '3s/[^=]+=\s*(.+)$/\1/p' filename

Por favor, eche un vistazo info sed. Por ejemplo, 3.2 y 4.7 son de particular interés para usted.

Nicholas
fuente
5
echo "POP3_SERVER_NAME = localhost" | sed 's/.*= //'
localhost

O si tiene el contenido en un archivo:

sed 's/.*= //' somefile.txt
localhost
Adam Siemion
fuente
ok, pero leí en mi archivo así: sed -n '3p' installation.sh
Mercer
2
@ Mercer: vea las actualizaciones que agregué a la respuesta.
slm
@Adam Siemion: gracias, pero ¿cómo indicar el número de línea?
Mercer
4

Puede usar el comando de corte, estableciendo el delímetro en '=' y luego imprimir el segundo campo de esta manera:

cut -d'=' -f2
anselal
fuente
3

Múltiples formas de hacerlo, teniendo en cuenta que su archivo se llama foobar:

Especifique el patrón a buscar:

PAT=POP3_SERVER_NAME

Extraer usando sed

sed -n "/$PAT/p" foobar | sed "s/$PAT = //"

O usando sedycut

sed -n "/$PAT/p" foobar | cut -d' ' -f3
unxnut
fuente
2

La belleza de Linux / Unix es que generalmente hay más de una forma de lograr algo. En el caso de la operación, hay al menos cuatro formas diferentes de extraer el nombre del servidor POP del archivo:

  1. grep POP3_SERVER_NAME installation.sh | cut -d'=' -f2
  2. grep POP3_SERVER_NAME installation.sh | awk '{print $3}'
  3. grep POP3_SERVER_NAME installation.sh | sed 's/.*= //'
  4. sed -n 's/^.*POP3_SERVER_NAME = //p' installation.sh
Thdoan
fuente