Equivalente de grep a awk ou sed

6

Eu quero saber o equivalente de

grep -oE '[^ ]+$' pathname

para awk ou sed. Se alguém puder responder e explicar isso seria ótimo. Obrigado.

    
por Harsh Patel 30.03.2017 / 16:14

4 respostas

3

Vamos repassar o que seu comando grep faz primeiro:

  • o -o indica grep para gerar apenas a parte correspondente em vez da linha inteira
  • o sinalizador -E permite o uso de expressões regulares estendidas
  • '[^ ]+$' corresponderá a qualquer caractere não espacial repetido uma ou mais vezes no final da linha - basicamente, uma palavra no final da linha.

Execução de teste:

$ cat input.txt
to be or not to be
that is the question
$ grep -oE '[^ ]+$' input.txt                                      
be
question

Agora, como podemos fazer o mesmo em awk ? Bem, isso é bastante fácil, considerando que awk opera por padrão em entradas separadas por espaços de cada linha (nós as chamamos de palavras - awk as chama de campos). Assim, poderíamos imprimir $NF com awk - pegar a variável NF para o número de campos e tratá-la como se referindo a uma específica. Mas observe que o comando grep corresponderia apenas a linhas não em branco, ou seja, há pelo menos uma palavra lá. Assim, precisamos de uma condição para awk - operar somente nas linhas que possuem NF de campos acima de zero.

awk 'NF{print $NF}' input.txt

Deve-se notar que o GNU awk, pelo menos, suporta o regex estendido (não estou familiarizado com os outros como extensivamente, por isso não vou fazer afirmações sobre os outros). Assim, podemos também escrever uma variação na resposta do cuonglm:

$ awk '{if(match($0,/[^ ]+$/)) print $NF}' input.txt               
be
question

Com o GNU sed também é possível usar expressões regulares estendidas - isso requer -r flag, mas você não pode simplesmente usar a mesma expressão regular. Há uma necessidade de usar backreference com .

$ cat input.txt                                                                                                          
to be or not to be
that is the question
blah 

$ sed -r -e 's/^.* ([^ ]+)$//' input.txt                                                                             
be
question
blah

É possível obter o resultado desejado com a expressão regular básica, assim:

$ cat input.txt                                                    
to be or not to be
that is the question
blah 
$ sed 's/^.* \([^ ].*\)$//' input.txt                           
be
question
blah 

Para mais informações, consulte estas postagens:

por 30.03.2017 / 21:22
6

awk é superconjunto de grep , então você também pode usar esse padrão grep em awk :

awk '{match($0, "[^ ]+$"); if (RSTART > 0) print substr($0, RSTART, RLENGTH)}'
    
por 30.03.2017 / 16:33
4

no awk:

awk 'NF>0 {print $NF}'     ## fails with end of line spaces; \thnaks{cuonglm}
awk '/[^ ]$/ {print $NF}'  ## fails with tabs in lasts field; \thanks{Terdon}
awk -F ' +'  '$NF {print $NF}'            ## too tricky  
awk 'match($0,/[^ ]+$/,a){print a[0]}'    ## follows def. of grep -o

No sed:

sed -nr 's/(|.* )([^ ]+)$//p'

\ thanks {cuonglm}

e (por que não?) em Perl

perl -nlE '/([^ ]+)$/ and say $1'
    
por 30.03.2017 / 16:35
0

Este é o equivalente do que você está tentando fazer com o grep:

# there is a space n a tab in the [...]
sed -ne '/[^  ]$/s/.*[    ]//p'

# this makes the code intent visually unambiguous
TAB='echo 'x' | tr 'x' '1''; # tab
SPC='echo 'x' | tr 'x' '0''; # space
h="[$SPC$TAB]";                 # whitespace
S="[^$TAB$SPC]";                # nonwhitespace

sed -ne "/$S\$/s/.*$h//p"

sed -ne "s/.*$h\($S$S*\)\$//p"
    
por 30.03.2017 / 18:43

Tags