Entendendo a expressão sed para substituir a última palavra de cada linha pela primeira

4

Eu tenho que substituir a última palavra de cada linha com a primeira. O código é:

$ sed "s/\(^a-z,0-9]*\)\(.*\)\([a-z,0-9]*$\)/\g". 

Eu não entendo essa parte \(^a-z,0-9]*\)\(.*\)\([a-z,0-9]*$\) especialmente \(.*\) .

    
por L.Robert 26.03.2017 / 17:28

2 respostas

10

Depois de corrigir os erros básicos da sintaxe, você tem:

sed "s/\(^[a-z,0-9]*\)\(.*\)\([a-z,0-9]*$\)//g"
  • s/old/new/ replace old com new
  • \(^[a-z,0-9]*\) salva qualquer número de letras minúsculas ou números no início da linha ( ^ é o início da linha) para mais tarde (referência posterior com )
  • \(.*\) Salva qualquer número de caracteres para mais tarde (para referência como )
  • \([a-z,0-9]*$\) salva qualquer número de letras minúsculas ou números no final da linha ( $ é o fim da linha) para mais tarde (referência como )
  • imprime o primeiro padrão, depois o segundo, depois o primeiro novamente
  • g isto é inapropriado nesta expressão. Isso significa atuar em várias correspondências na mesma linha, mas nossa expressão precisa ler a linha inteira, portanto, g não faz sentido e deve ser omitido.

Isso ainda não funcionará, porque expressões regulares são gananciosas, então o meio \(.*\) corresponde a tudo depois da primeira palavra, resultando na reimpressão da primeira palavra no final da linha sem substituir nada.

Você pode corrigi-lo (adicionando também I para pesquisa sem distinção entre maiúsculas e minúsculas):

sed "s/\(^[a-z,0-9]*\) \(.*\) \([a-z,0-9]*$\)/  /I"

Se você quiser incluir outros caracteres além de letras e números:

sed -r 's/^([^ ]+) (.*) ([^ ]+)$/  /'
  • -r usa ERE (salva usando todas as barras invertidas)
  • [^ ]+ pelo menos um dos caracteres exceto espaços
por Zanna 26.03.2017 / 18:11
4

Eu não acho que o seu código vá funcionar aqui porque é simplesmente malformado. Eu reescrevi toda a expressão. Supondo que todas as linhas começam e terminam com palavras que contenham apenas números e letras do alfabeto, você pode tentar:

$ echo -en "foo bar baz\nThe Good, the Bad and the Ugly\n" | \
> sed 's/^\(\<[[:alpha:]]\+\>\)\(.*\)\<[[:alpha:]]\+\>$//g'
foo bar foo
The Good, the Bad and the The

Breve explicação:

s/PATTERN/SUBSTITUTION_STRING/g - PATTERN é o que procuramos e SUBSTITUTION_STRING é o que vamos substituir por esse padrão. g significa que toda a linha será verificada, em vez de ir apenas para a primeira correspondência encontrada na linha.

^\(\<[[:alpha:]]\+\>\) - se uma linha começar com um limite de palavra que é seguido por mais de um caractere alfanumérico seguido por outro limite de palavra, salve tudo isso na variável .

\<[[:alpha:]]\+\>$ - a mesma coisa exata aqui, mas estamos usando isso apenas para identificar a localização da última palavra.

\(.*\) - qualquer coisa entre será salva na variável .

- a mesma linha com a última palavra substituída pela primeira.

    
por misha 26.03.2017 / 22:06