Imprimir una parte específica en una salida

11

Supongamos que hay un comando como:

cat /boot/config-3.19.0-32-generic | grep CONFIG_ARCH_DEFCONFIG

La salida es como tal:

CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"

Ahora, mi pregunta es: ¿Hay algún comando que solo imprima lo que está dentro de las comillas, es decir " ",?

¿Y podría explicar un poco el comando? ¡Gracias! por adelantado.

Rafael
fuente
55
Tenga caten cuenta que usarlo en una tubería es casi siempre un desperdicio de recursos (AKA UUOC ); greppuede leer su entrada de un archivo ya (es decir, grep CONFIG_ARCH_DEFCONFIG /boot/config-3.19.0-32-generichace exactamente lo mismo, pero 1. Es más corto 2. Es más fácil de entender 3. No bifurca un shell adicional y un proceso adicional). En el 99% de los casos, usar cat al comienzo de la tubería sin concatenar múltiples archivos es simplemente dañino. :)
kos
@kos - ¡Gracias! No lo sabía, ya que acabo de comenzar a usar Linux. Lo tendré en cuenta.
Raphael
¡Notario público! Dejo mi comentario anterior para otras personas que se encuentran con esta pregunta.
Kos
La inicial cat, aunque inútil en este caso, facilitaría la edición de toda la línea de comandos en el futuro en caso de que desee cambiar / agregar / eliminar algo más tarde, tal vez a tro cut, etc., no tenga que buscar y mover el nombre de archivo , asegúrese de que el otro comando lo admita, busque dónde colocarlo, etc. Y para un pequeño archivo de prueba solo agrega 0.002s. (Probablemente he pasado más tiempo escribiendo esto de lo que ahorraré en toda una vida evitando lo superfluo cat)
Xen2050
1
@ Xen2050 ¿por qué la catayuda aquí? Puedes hacerlo grep foo file | tro ... | cuttan fácilmente como cat file | tr | grep .... El catsolo agrega cinco caracteres adicionales, una tubería adicional y una llamada de programa adicional y no simplifica nada.
terdon

Respuestas:

15

Si tu puedes hacerlo. Tu comando sería:

cat /boot/config-3.19.0-32-generic | grep CONFIG_ARCH_DEFCONFIG | awk -F'"' '{print $2}'

que solo devolvería:

arch/x86/configs/x86_64_defconfig

El awkcomando usa separadores de campo con el -Fcomando, y para configurarlo para usar comillas dobles, lo escribe con comillas simples alrededor -F'"'. Luego, '{print $2}'le dice a awk que imprima el segundo conjunto después del separador de campo.

¡Espero que esto ayude!

Terrance
fuente
14
@Terrance, en este caso, este es un uso inútil de caty grep. Podrías reemplazar caty partir grepcon awk -F'"' '/CONFIG_ARCH_DEFCONFIG/{print $2}' /boot/config-3.19.0-32-generic . Menos fontanería, dejando que AWK haga todo el trabajo, que es más que capaz de hacer
Sergiy Kolodyazhnyy
De acuerdo con @Serg
Tung Tran
@Serg Sin problemas. Entiendo lo que dices. Solo estaba agregando a su comando original agregando el awkcomando. =)
Terrance
11

Puedes hacerlo con un solo grepcomando:

grep -Po '^CONFIG_ARCH_DEFCONFIG="\K[^"]*' /boot/config-3.19.0-32-generic

O (un poco más largo y más convulsionado):

grep -Po '^CONFIG_ARCH_DEFCONFIG="\K.*?(?=")' /boot/config-3.19.0-32-generic
  • -P: le dice grepque interprete el patrón como PCRE (expresión regular compatible con Perl);
  • -o: le dice grepque imprima solo la coincidencia;
  • ^CONFIG_ARCH_DEFCONFIG=": coincide con una CONFIG_ARCH_DEFCONFIG="cadena al comienzo de la línea;
  • \K: descarta la subcadena previamente coincidente;

# 1:

  • [^"]*: coincide con cualquier número de cualquier carácter que no sea "(con avidez).

# 2:

  • .*?: coincide con cualquier número de cualquier personaje (perezosamente);
  • (?="): lookahead (aserción de longitud cero, no coincide con ningún carácter); coincide si el siguiente carácter es a ".
% grep -Po '^CONFIG_ARCH_DEFCONFIG="\K[^"]*' /boot/config-4.2.0-16-generic
arch/x86/configs/x86_64_defconfig
% grep -Po '^CONFIG_ARCH_DEFCONFIG="\K.*?(?=")' /boot/config-4.2.0-16-generic
arch/x86/configs/x86_64_defconfig
kos
fuente
Me encanta aprender más de una forma de lograr los mismos resultados. ¡Gran respuesta! =)
Terrance
10

Hay muchas maneras de desollar a este gato, aquí hay una sedmanera:

sed -nr 's/^CONFIG_ARCH_DEFCONFIG="([^"]+)"$/\1/p' /boot/config-3.19.0-32-generic

Aquí estamos haciendo coincidir la línea y capturando la porción deseada, es decir, la porción entre comillas dobles ( ([^"]+)) y luego reemplazando toda la línea con el grupo capturado ( \1) solamente.

Ejemplo:

% sed -nr 's/^CONFIG_ARCH_DEFCONFIG="([^"]+)"$/\1/p' /boot/config-3.13.0-32-generic
arch/x86/configs/x86_64_defconfig
heemayl
fuente
10

Qué, no hay perl?

grep CONFIG_ARCH_DEFCONFIG /boot/config-3.19.0-32-generic | 
    perl -pe 's/.*?"([^"]*).*/$1/'

El perlse -print cada línea después de aplicar la secuencia de comandos dada por -e. La s/foo/bar/sustituirá foocon bar. Los patrones entre paréntesis se "capturan" y pueden denominarse $1, $2... $Ndonde $1se captura el primer patrón, $2el segundo, etc. La expresión regular buscará todo hasta la primera cita ( .*?"), luego capturará 0 o más "caracteres que no sean caracteres. ( [^"]*) y luego todo lo demás. Todo se reemplaza con el patrón capturado.

También puede dejar que el patrón coincida con perl:

perl -ne 's/.*CONFIG_ARCH_DEFCONFIG="([^"]*).*/$1/ && print' /boot/config-3.19.0-32-generic
terdon
fuente
2
Sabía que te
unirías
entonces produciría un código de Python ..
Avinash Raj
with open('/boot/config-3.19.0-32-generic') as f: for line in f: if line.startswith('CONFIG_ARCH_DEFCONFIG'): print line.split('"')[1]
Avinash Raj
@AvinashRaj cosas buenas, ¿quieres publicar esto por favor? También publiqué uno con expresiones regulares.
Sergiy Kolodyazhnyy
8

Aquí hay una combinación de grepy cut, que hace el mismo trabajo.

$ grep "CONFIG_ARCH_DEFCONFIG" /boot/config-3.19.0-32-generic | cut -d"\"" -f2                                                
arch/x86/configs/x86_64_defconfig

Explicación:

  • grep "CONFIG_ARCH_DEFCONFIG" /boot/config-3.19.0-32-generices la parte que se encuentra la línea, en la sintaxis estándar grep: grep [OPTIONS] PATTERN [FILE...]. La salida pasa por la tubería a la siguiente etapa.
  • cut -d"\"" -f2. Esta parte utiliza texto cortado a recortado separado por un delimitador específico (que se especifica con una -dmarca). Tenemos que escapar de la comilla doble con barra invertida para que el shell permita tomar comillas dobles como una de las opciones del cutcomando, en lugar de ingresarlo en el shell. Ahora cutva a tratar de salida de grepcomo separadas por "y se dividió en tres columnas, CONFIG_ARCH_DEFCONFIG, arch/x86/configs/x86_64_defconfig, y el espacio vacío. La línea que necesitamos es la segunda columna, lo que significa que necesitamos usar -f2flag.
Sergiy Kolodyazhnyy
fuente
3

Como actualmente estoy aprendiendo pythonaquí, hay una versión que usa exactamente eso.

#!/usr/bin/env python
import re

reg = re.compile('CONFIG_ARCH_DEFCONFIG')

with open("/boot/config-3.19.0-32-generic") as file :
   for line in file:
       if reg.match(line):
           print line.split('"')[1]

Ejecución de muestra:

DIR:/TECH-BOOKS
skolodya@ubuntu:$ ./extractString.py                                           
arch/x86/configs/x86_64_defconfig

DIR:/TECH-BOOKS
skolodya@ubuntu:$ cat ./extractString.py                                       
#!/usr/bin/env python
import re

reg = re.compile('CONFIG_ARCH_DEFCONFIG')

with open("/boot/config-3.19.0-32-generic") as file :
   for line in file:
       if reg.match(line):
           print line.split('"')[1]
Sergiy Kolodyazhnyy
fuente
la sangría es muy7 muy importante en python ..
Avinash Raj
1
No necesita ir a regexd, solo use el mío, es decir, line.startswithporque re.matches mucho más lento questartswith
Avinash Raj