Stampa una parte specifica in un output


11

Supponiamo che esista un comando come:

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

L'output è come tale:

CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"

Ora, la mia domanda è: ci sono dei comandi che stamperanno solo ciò che è all'interno delle virgolette, cioè " "?

E potresti per favore spiegare un po 'il comando? Grazie! in anticipo.


5
Si noti che l'utilizzo catin una pipe è quasi sempre uno spreco di risorse (AKA UUOC ); greppuò già leggere il suo input da un file (cioè grep CONFIG_ARCH_DEFCONFIG /boot/config-3.19.0-32-genericfa esattamente la stessa cosa, ma 1. È più corto 2. È più facile da capire 3. Non esegue il fork di una shell aggiuntiva e di un processo aggiuntivo). Nel 99% dei casi, usare cat all'inizio della pipe senza concatenare più file è dannoso. :)
kos

@kos - Grazie! Non lo sapevo poiché ho appena iniziato a usare Linux. Lo terrò a mente.
Raffaello,

Np! Lascio il mio commento sopra per altre persone che si imbattono in questa domanda.
kos

L'iniziale cat, sebbene in questo caso inutile, renderebbe più semplice la modifica dell'intera riga di comandi in futuro nel caso in cui si desideri modificare / aggiungere / rimuovere qualcosa in seguito, forse un tro cut, ecc., Non è necessario trovare e spostare il nome file , assicurati che l'altro comando lo supporti, trova dove inserirlo, ecc. E per un piccolo file di test aggiunge solo 0,002 secondi. (Probabilmente ho speso più tempo a scrivere questocat
codice di quanto non riuscirò

1
@ Xen2050 perché l' cataiuto qui? Puoi farlo grep foo file | tro ... | cutcon la stessa facilità cat file | tr | grep .... Il catsolo aggiunge un extra di cinque personaggi, un tubo in più e una chiamata di programma in più e non lo fa semplificare nulla.
terdon,

Risposte:


15

Si, puoi farlo. Il tuo comando sarebbe:

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

che restituirebbe solo:

arch/x86/configs/x86_64_defconfig

Il awkcomando usa i separatori di campo con il -Fcomando e per impostarlo in modo che utilizzi le virgolette doppie, lo si digita con virgolette singole attorno ad esso come -F'"'. Quindi '{print $2}'dice a awk di stampare il secondo set dopo il separatore di campo.

Spero che questo ti aiuti!


14
@Terrance, in questo caso si tratta di un uso inutile di cate grep. È possibile sostituire cate grepseparare awk -F'"' '/CONFIG_ARCH_DEFCONFIG/{print $2}' /boot/config-3.19.0-32-generic . Meno impianti idraulici, lasciando che AWK faccia tutto il lavoro, cosa che è più che in grado di fare
Sergiy Kolodyazhnyy,

Concordo con @Serg
Tung Tran il

@Serg Nessun problema. Capisco quello che stai dicendo. Stavo solo aggiungendo al suo comando originale aggiungendo il awkcomando. =)
Terrance

11

Puoi farlo con un solo grepcomando:

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

Oppure (un po 'più lungo e più convinto):

grep -Po '^CONFIG_ARCH_DEFCONFIG="\K.*?(?=")' /boot/config-3.19.0-32-generic
  • -P: dice grepdi interpretare il pattern come un PCRE (Perl Regular Regular Expression);
  • -o: dice grepdi stampare solo la corrispondenza;
  • ^CONFIG_ARCH_DEFCONFIG=": corrisponde a una CONFIG_ARCH_DEFCONFIG="stringa all'inizio della riga;
  • \K: scarta la sottostringa precedentemente abbinata;

# 1:

  • [^"]*: corrisponde a qualsiasi numero di qualsiasi personaggio non "(avidamente).

# 2:

  • .*?: corrisponde a qualsiasi numero di qualsiasi personaggio (pigramente);
  • (?="): lookahead (affermazione a lunghezza zero, non corrisponde a nessun personaggio); corrisponde se il seguente carattere è 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

Adoro imparare più di un modo per ottenere gli stessi risultati. Bella risposta! =)
Terrance

10

Esistono molti modi per scuoiare questo gatto, ecco un sedmodo:

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

Qui stiamo abbinando la linea e catturando la porzione desiderata, cioè la porzione tra virgolette doppie ( ([^"]+)) e quindi sostituendo l'intera linea solo con il gruppo acquisito ( \1).

Esempio:

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

10

Cosa no perl?

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

La perlsi -pRint ogni linea dopo l'applicazione dello script data dal -e. La s/foo/bar/sostituirà foocon bar. Patterns in parentesi sono "catturati" e possono essere indicati come $1, $2... $Ndove $1è il primo modello catturato, $2il secondo etc. L'espressione regolare cercherà per tutto fino alla prima citazione ( .*?"), quindi catturare 0 o più non "caratteri ( [^"]*) e poi tutto il resto. Il tutto viene sostituito con il modello acquisito.

Puoi anche lasciare il pattern corrispondente a perl:

perl -ne 's/.*CONFIG_ARCH_DEFCONFIG="([^"]*).*/$1/ && print' /boot/config-3.19.0-32-generic

2
Sapevo che ti saresti unito ad un certo punto: P +1
heemayl

poi produrrei un codice 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 roba buona, ti interessa pubblicare questo per favore? Ne ho pubblicato uno anche con regex.
Sergiy Kolodyazhnyy,

8

Ecco una combinazione di grepe cut, che fa lo stesso lavoro.

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

Spiegazione:

  • grep "CONFIG_ARCH_DEFCONFIG" /boot/config-3.19.0-32-genericè la parte che trova la linea, nella sintassi standard di grep: grep [OPTIONS] PATTERN [FILE...]. L'uscita passa attraverso il tubo allo stadio successivo
  • cut -d"\"" -f2. Questa parte usa il testo tagliato per ritagliare separato da delimitatore specifico (che è specificato con -dflag). Dobbiamo sfuggire alla doppia virgoletta con la barra rovesciata in modo che la shell consenta di prendere la doppia virgoletta come una delle opzioni al cutcomando, anziché l'input alla shell stessa. Ora cuttratterà output grepcome separato da "e divisa in tre colonne, CONFIG_ARCH_DEFCONFIG, arch/x86/configs/x86_64_defconfig, e lo spazio vuoto. La linea di cui abbiamo bisogno è la seconda colonna, ciò significa che dobbiamo usare -f2flag.

3

Dal momento che sto imparando pythonqui ecco una versione che usa esattamente questo.

#!/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]

Esecuzione di esempio:

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]

il rientro è molto importante per Python. 7
Avinash Raj,

1
Non hai bisogno di andare su regexd, usa solo il mio, line.startswithperché re.matchè molto più lento distartswith
Avinash Raj,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.