Ajuda a entender o comando 'sed'

1

Esta é uma pergunta que eu errei em um teste.

Suponha que um arquivo names contenha uma lista de nomes no formulário: "firstname lastname", um por linha. Esses nomes não são classificados e você deseja que eles sejam classificados pelo sobrenome. No entanto, o formato dos nomes em cada linha deve permanecer o mesmo. Quais UM dos seguintes comandos irão NÃO produzir uma lista de nomes devidamente classificada para a consola?

[ ]cut -f 2 -d " " names | paste names - | sort -k 3 | cut -f 1

[x]sort -k 2 names ← Wrong answer

[ ]sed 's/\(\w*\) \(\w*\)/ /' names | sort | cut -f 2-3 -d " "

[ ]cut -f 2 -d " " names | sort

[ ]cut -f 2 -d " " names | paste - names | sort | cut -f 2

O que eu não entendo é como o seguinte produz a saída solicitada:

sed 's/\(\w*\) \(\w*\)/  /' names | sort | cut -f 2-3 -d " "

I.E. classifica os nomes em ordem alfabética pelo sobrenome mas preservando o formato de "sobrenome sobrenome". Como o \w seguido por um * funciona? Eu pensei que um nome de arquivo precedido por um espaço tinha que seguir. Como o \w se aplica aqui?

    
por user284179 27.07.2018 / 19:33

1 resposta

3

Note que o abaixo só se aplica ao GNU sed ; BSD sed se comportará de maneira diferente.

Ok, vamos dar um passo a passo, usando isso para o conteúdo de names :

Alice Zylanzy
Zepher Applecart
Michael Copperside

Aceitaremos o comando e passaremos por ele para ver como funciona:

$ sed 's/\(\w*\) \(\w*\)/  /' names
Zylanzy Alice Zylanzy
Applecart Zepher Applecart
Copperside Michael Copperside

Portanto, o comando sed dá um sobrenome duplicado na frente da linha. Em seguida, fazemos um simples sort :

$ sed 's/\(\w*\) \(\w*\)/  /' names | sort
Applecart Zepher Applecart
Copperside Michael Copperside
Zylanzy Alice Zylanzy

Legal, agora eles estão classificados por sobrenome. Agora usamos cut para nos livrarmos do prefixo que usamos:

$ sed 's/\(\w*\) \(\w*\)/  /' names | sort | cut -f 2-3 -d " "
Zepher Applecart
Michael Copperside
Alice Zylanzy

.. e Bob é seu tio, como eles dizem.

Entrando nas ervas daninhas de como o comando sed funciona: \w é um encantamento mágico que significa "caractere de palavra", que é uma abreviação de /[0-9A-Za-z_]/ . \w* simplesmente significa zero ou mais "caracteres de palavra", que é como os nomes são agrupados. Presumindo que nenhum dos nomes tenha sublinhados ou numerais, pode ser reescrito como:

sed 's/\([A-Za-z]*\) \([A-Za-z]*\)/  /' names

Para desmembrar todo o comando sed peça por peça:

O comando sed s é um comando "pesquisar e substituir" ou "substituir". A expressão entre o primeiro e o segundo / s é substituída pelo que está entre o segundo e o terceiro / s.

Então, estamos substituindo isso:

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  (                        group and capture to :
    \w*                      word characters (a-z, A-Z, 0-9, _) (0 or
                             more times (matching the most amount
                             possible))
  )                        end of 
                           ' '
  (                        group and capture to :
    \w*                      word characters (a-z, A-Z, 0-9, _) (0 or
                             more times (matching the most amount
                             possible))
  )                        end of 

Com isso:

NODE                     EXPLANATION
--------------------------------------------------------------------------------
                         what was matched by capture 
                           ' '
                         what was matched by capture 
                           ' '
                         what was matched by capture 
    
por 27.07.2018 / 19:48

Tags