Imprimir uma peça específica em uma saída

11

Suponhamos que exista um comando como:

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

A saída é a seguinte:

CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"

Agora, minha pergunta é: Existe algum comando que imprima apenas o que está dentro das vírgulas invertidas, ou seja " ",?

E você poderia explicar um pouco o comando? Obrigado! antecipadamente.

Rafael
fonte
5
Observe que o uso catem um tubo é quase sempre um desperdício de recursos (AKA UUOC ); grepjá pode ler sua entrada de um arquivo (ou seja, grep CONFIG_ARCH_DEFCONFIG /boot/config-3.19.0-32-genericfaz exatamente a mesma coisa, mas 1. É mais curto 2. É mais fácil de entender 3. Ele não bifurca um shell adicional e um processo adicional). Em 99% dos casos, usar o gato no início do tubo sem concatenar vários arquivos é apenas prejudicial. :)
kos
@kos - Thanx! Não sabia disso, porque eu comecei a usar o Linux. Manterá isso em mente.
Raphael
Np! Estou deixando meu comentário acima para outras pessoas que se deparam com essa questão.
kos
A inicial cat, embora inútil nesse caso, facilitaria a edição de toda a linha de comandos no futuro, caso você queira alterar / adicionar / remover algo mais tarde, talvez um trou cut, etc., não precise localizar e mover o nome do arquivo , verifique se o outro comando o suporta, encontre onde colocá-lo etc. E para um pequeno arquivo de teste, ele adiciona apenas 0,002s. (Eu provavelmente passou mais tempo digitando isso do que eu jamais vou guardar na vida de evitar supérfluos cat's)
Xen2050
1
@ Xen2050 por que a catajuda aqui? Você pode fazer grep foo file | trou ... | cuttão facilmente quanto cat file | tr | grep .... O catjust adiciona cinco caracteres extras, um pipe extra e uma chamada de programa extra e não simplifica nada.
terdon

Respostas:

15

Sim, você pode fazer isso. Seu comando seria:

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

que retornaria apenas:

arch/x86/configs/x86_64_defconfig

O awkcomando usa separadores de campo com o -Fcomando e, para configurá-lo para usar aspas duplas, você o digita com aspas simples à sua volta -F'"'. Em seguida, o '{print $2}'comando awk para imprimir o segundo conjunto após o separador de campos.

Espero que isto ajude!

Terrance
fonte
14
@Terrance, neste caso, este é um uso inútil de cate grep. Você pode substituir cate grepparticipar awk -F'"' '/CONFIG_ARCH_DEFCONFIG/{print $2}' /boot/config-3.19.0-32-generic . Menos encanamento, deixando o AWK fazer todo o trabalho, o que é mais do que capaz de fazer #
Sergiy Kolodyazhnyy
Concordo com @Serg
Tung Tran
@Serg Sem problemas. Eu entendo o que você está dizendo. Eu estava apenas adicionando ao seu comando original adicionando o awkcomando. =)
Terrance
11

Você pode fazer isso com um único grepcomando:

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

Ou (um pouco mais longo e mais convencido):

grep -Po '^CONFIG_ARCH_DEFCONFIG="\K.*?(?=")' /boot/config-3.19.0-32-generic
  • -P: indica greppara interpretar o padrão como um PCRE (Perl Compatible Regular Expression);
  • -o: diz greppara imprimir apenas a correspondência;
  • ^CONFIG_ARCH_DEFCONFIG=": corresponde a uma CONFIG_ARCH_DEFCONFIG="sequência no início da linha;
  • \K: descarta a substring correspondida anteriormente;

# 1:

  • [^"]*: corresponde a qualquer número de qualquer caractere que não seja "(avidamente).

# 2:

  • .*?: corresponde a qualquer número de qualquer caractere (preguiçosamente);
  • (?="): lookahead (afirmação de comprimento zero, não corresponde a nenhum caractere); corresponde se o caractere a seguir for 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
fonte
Adoro aprender mais de uma maneira de obter os mesmos resultados. Ótima resposta! =)
Terrance
10

Existem muitas maneiras de esfolar esse gato, aqui está uma sedmaneira:

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

Aqui, estamos combinando a linha e capturando a parte desejada, ou seja, a parte entre aspas duplas ( ([^"]+)) e, em seguida, substituindo a linha inteira pelo grupo capturado ( \1).

Exemplo:

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

O que não perl?

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

O perlirá -pcriar todas as linhas depois de aplicar o script fornecido por -e. O s/foo/bar/substituirá foocom bar. Padrões em parênteses são "capturados" e pode ser referido como $1, $2... $Nonde $1é o 1º padrão capturado, $2o segundo etc. A expressão regular irá procurar por tudo até a primeira citação ( .*?"), em seguida, capturar a 0 ou mais não "caracteres ( [^"]*) e depois todo o resto. A coisa toda é substituída pelo padrão capturado.

Você também pode deixar o padrão correspondente a perl:

perl -ne 's/.*CONFIG_ARCH_DEFCONFIG="([^"]*).*/$1/ && print' /boot/config-3.19.0-32-generic
Terdon
fonte
2
Eu sabia que você entraria em algum momento: P +1
heemayl
então eu iria produzir um código 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 coisas boas, gostaria de postar isso por favor? Eu publiquei um com regex também.
Sergiy Kolodyazhnyy
8

Aqui está uma combinação de grepe cut, que faz o mesmo trabalho.

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

Explicação:

  • grep "CONFIG_ARCH_DEFCONFIG" /boot/config-3.19.0-32-genericé a parte que se encontra a linha, na sintaxe grep padrão: grep [OPTIONS] PATTERN [FILE...]. A saída passa pelo tubo para a próxima etapa
  • cut -d"\"" -f2. Esta parte usa o recorte para cortar o texto separado por delimitador específico (que é especificado com -dsinalizador). Temos que escapar da aspas duplas com barra invertida para que o shell permita tomar aspas duplas como uma das opções do cutcomando, em vez de inserir a própria shell. Agora cutirá tratar a saída de grepcomo separados por "e dividiu-se em três colunas, CONFIG_ARCH_DEFCONFIG, arch/x86/configs/x86_64_defconfig, e o espaço vazio. A linha que precisamos é a segunda coluna, isso significa que precisamos usar o -f2sinalizador.
Sergiy Kolodyazhnyy
fonte
3

Como atualmente estou aprendendo, pythonaqui está uma versão usando exatamente isso.

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

Exemplo de execução:

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
fonte
recuo é muito7 muito importante em python ..
Avinash Raj
1
Você não precisa ir para o regexd, basta usar o meu, ou seja, line.startswithporque re.matché muito mais lento que o #startswith
Avinash Raj