Executa a pesquisa regex em uma linha previamente correspondida por regex (one-liner)

0

Eu preciso imprimir uma string que esteja em uma linha exclusiva em um arquivo de texto longo. Exemplo de linha relevante no arquivo long.txt :

Software version 4.0.10, 2002-03-28

A string desejada é exatamente 4.0.10 .

Os passos provavelmente são:

  • Corresponda a linha; por exemplo. com um regexp como /^Software/
  • Uma vez que a linha foi encontrada, faça uma pesquisa nela para a string desejada (outro regexp)
  • Imprimir a string

Como posso fazer isso em uma linha (sem pipes) com ferramentas como sed , awk ou perl ?

Observação: o regex real não é tão relevante. O que mais importa são os comandos e a sintaxe envolvidos. Obrigado!

    
por undostres 29.03.2016 / 01:21

3 respostas

1

Aqui estão algumas opções para você

sed -n 's/Software version \([^,]\+\).*//p' file
awk -F '[ ,]' '$1=="Software" && $2=="version" {print $3}' file
perl -nE '/Software version (.+?),/ and say $1' file
grep -oP '(?<=Software version ).+?(?=,)' file

Todos assumem que não há vírgulas na string de versão.

    
por 29.03.2016 / 15:37
2

Sua pergunta é bem geral; Gostaria de ter um momento para discutir o design de sed e como ele funciona para lidar com esses casos de uso.

sed é o editor de fluxo. Ele aceita entrada de texto em um fluxo - seja de um pipe, de um único arquivo ou de uma sequência de arquivos, um após o outro - executa ações nesse fluxo de texto e produz texto. (Note que não é intencionado ou projetado para edição de arquivos em sua concepção original, embora seja freqüentemente colocado em serviço para esse propósito.)

As notas principais da operação de sed que você deve entender são:

  • sed lida com texto linha por linha. O (s) comando (s) que você fornece é essencialmente um loop que opera em cada linha de entrada (por padrão) e imprime o resultado no final (por padrão).
  • Um comando em sed consiste em um teste condicional opcional (ou "padrão") e uma ação a ser executada.
  • Todas as ações são um comando de caractere único, por exemplo p rint, s ubstitute, d elete
  • A condição mais comum é a regex a ser comparada com a linha, mas os números de linha também podem ser usados.
  • Um intervalo pode ser especificado, significando: Faça a seguinte ação para todas as linhas de (primeira condição) até (segunda condição) .

Existe um tutorial muito completo e referência sobre sed disponível on-line gratuito, que eu recomendo ler em cheio.

Para o seu cenário, o comando que você quer é algo como:

sed -n -e '/^Software/{s/,.*//;s/.*[[:space:]]//;p;}' filename

Que se traduz em:

  • -n : suprima a ação padrão de sed de imprimir cada linha de entrada
  • -e : Execute seguindo o comando sed
  • /^Software/ : execute o seguinte conjunto de comandos contidos em {} , apenas nas linhas que correspondem a essa expressão regular
  • s/,.*// : remova a primeira vírgula da linha (e tudo depois dela)
  • s/.*[[:space:]]// : remova tudo até o último caractere de espaço em branco na linha
  • p : imprime o texto resultante.
por 29.03.2016 / 01:44
1

Experimente esta versão testada:

 awk '{if ($0 ~ /^Software/) {print substr($3,1,length($3)-1)}}' long.txt

Imprime o terceiro elemento de cada linha, começando com Software .

substr é usado para remover o último caractere ', ' do terceiro elemento.

O teste:

awk '{if ($0 ~ /^Software/) {print substr($3,1,length($3)-1)}}' long.txt
4.0.10
    
por 29.03.2016 / 01:47