Retorna apenas a parte de uma linha após um padrão correspondente

92

Então, abrir um arquivo com cat e, em seguida, usar grep para obter linhas de correspondência só me ajuda quando estou trabalhando com o conjunto de registros específico com o qual estou lidando. Ele precisa de uma maneira de combinar as linhas com um padrão, mas apenas para retornar a parte da linha após a partida. A parte antes e depois da partida varia constantemente. Eu joguei usando sed ou awk , mas não consegui descobrir como filtrar a linha para deletar a parte antes da partida, ou apenas retornar a parte após a partida, ou irá funcionar. Este é um exemplo de uma linha que preciso filtrar:

2011-11-07T05:37:43-08:00 <0.4> isi-udb5-ash4-1(id1) /boot/kernel.amd64/kernel: [gmp_info.c:1758](pid 40370="kt: gmp-drive-updat")(tid=100872) new group: <15,1773>: { 1:0-25,27-34,37-38, 2:0-33,35-36, 3:0-35, 4:0-9,11-14,16-32,34-38, 5:0-35, 6:0-15,17-36, 7:0-16,18-36, 8:0-14,16-32,34-36, 9:0-10,12-36, 10-11:0-35, 12:0-5,7-30,32-35, 13-19:0-35, 20:0,2-35, down: 8:15, soft_failed: 1:27, 8:15, stalled: 12:6,31, 20:1 }

A parte que eu preciso é tudo depois de "parado".

O pano de fundo por trás disso é que posso descobrir com que frequência algo atrasa:

cat messages | grep stalled | wc -l

O que eu preciso fazer é descobrir quantas vezes um certo nodo parou (indicado pela porção antes de cada dois pontos depois de "parado". Se eu apenas grep para isso (ou seja, 20 :) ele pode retornar linhas que têm soft Eu preciso filtrar apenas a parte paralisada para que eu possa, em seguida, grep para um nó específico daqueles que estão paralisados.

Para todos os efeitos, este é um sistema freebsd com utilitários padrão GNU, mas não consigo instalar nada extra para ajudar.

    
por MaQleod 08.11.2011 / 00:18

3 respostas

118

A ferramenta canônica para isso seria sed .

sed -n -e 's/^.*stalled: //p'

Explicação detalhada:

  • -n significa não imprimir nada por padrão.
  • -e é seguido por um comando sed.
  • s é o comando de substituição de padrão.
  • A expressão regular ^.*stalled: corresponde ao padrão que você está procurando, mais qualquer texto anterior ( .* significa qualquer texto, com um inicial ^ para dizer que a correspondência começa no início da linha). Observe que, se stalled: ocorrer várias vezes na linha, isso corresponderá à última ocorrência.
  • A correspondência, ou seja, tudo na linha até stalled: , é substituído pela string vazia (ou seja, excluída).
  • O% final p significa imprimir a linha transformada.

Se você quiser manter a parte correspondente, use uma referência anterior: na peça de substituição designa o que está dentro de um grupo \(…\) no padrão. Aqui, você poderia escrever stalled: novamente na peça de substituição; esse recurso é útil quando o padrão que você está procurando é mais geral do que uma string simples.

sed -n -e 's/^.*\(stalled: \)//p'

Às vezes, você deseja remover a parte da linha após a partida. Você pode incluí-lo na partida incluindo .*$ no final do padrão (qualquer texto .* seguido do final da linha $ ). A menos que você coloque essa parte em um grupo que você referencie no texto de substituição, o final da linha não estará na saída.

Como ilustração adicional de grupos e referências anteriores, este comando troca a parte antes da partida e a parte depois da partida.

sed -n -e 's/^\(.*\)\(stalled: \)\(.*\)$//p'
    
por 08.11.2011 / 01:22
61

A outra ferramenta canônica que você já usa: grep :

Por exemplo:

grep -o 'stalled.*'

Tem o mesmo resultado que a segunda opção de Gilles:

sed -n -e 's/^.*\(stalled: \)//p'

O sinalizador -o retorna a parte --only-matching da expressão, portanto, não a linha inteira que é - obviamente - normalmente feita pelo grep.

Para remover o "parado:" da saída, podemos usar uma terceira ferramenta canônica, cortar:

grep -o 'stalled.*' | cut -f2- -d:

O comando cut usa o delimitador : e imprime o campo 2 até o final. É uma questão de preferência, claro, mas a sintaxe cut eu acho muito fácil de lembrar.

    
por 08.08.2014 / 13:46
4

Eu usei ifconfig | grep eth0 | cut -f3- -d: para levar isso

    [root@MyPC ~]# ifconfig
    eth0  Link encap:Ethernet  HWaddr AC:B4:CA:DD:E6:F8
          inet addr:192.168.0.2  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:78998810244 errors:1 dropped:0 overruns:0 frame:1
          TX packets:20113430261 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:110947036025418 (100.9 TiB)  TX bytes:15010653222322 (13.6 TiB)

e faça com que pareça com isso

    [root@MyPC ~]# ifconfig | grep eth0 | cut -f3- -d:
    C4:7A:4D:F6:B8

Espero que isso ajude.

    
por 31.03.2017 / 06:52