sed substitua todas as guias e espaços por um único espaço

23

Eu tenho uma string como a seguinte:

test.de.          1547    IN      SOA     ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600

agora eu quero substituir todas as guias / espaços entre os registros por apenas um único espaço para que eu possa usá-lo facilmente com cut -d " "

Eu tentei o seguinte:

sed "s/[\t[:space:]]+/[:space:]/g"

e várias variações, mas não conseguiu fazê-lo funcionar. Alguma ideia?

Zulakis
fonte
Tente: sed -r -e "s / [\ t \] + / / g"
RJS
A sua opção de cutsuporte -w?
Kondybas

Respostas:

40

Usar sed -e "s/[[:space:]]\+/ /g"

Aqui está uma explicação:

[   # start of character class

  [:space:]  # The POSIX character class for whitespace characters. It's
             # functionally identical to [ \t\r\n\v\f] which matches a space,
             # tab, carriage return, newline, vertical tab, or form feed. See
             # https://en.wikipedia.org/wiki/Regular_expression#POSIX_character_classes

]   # end of character class

\+  # one or more of the previous item (anything matched in the brackets).

Para sua substituição, você deseja inserir apenas um espaço. [:space:]não funcionará lá, pois é uma abreviação para uma classe de personagem e o mecanismo de expressão regular não saberia qual caractere colocar lá.

O +escape deve ser escapado no regex porque, com o mecanismo de regex do sed, +é um caractere normal, enquanto \+é um metacaractere de 'um ou mais'. Na página 86 de Mastering Regular Expressions , Jeffrey Friedl menciona em uma nota de rodapé que ed e grep usavam parênteses escapados porque "Ken Thompson achou que expressões regulares seriam usadas para trabalhar principalmente com código C, onde a necessidade de combinar parênteses brutos seria mais comum do que a referência remota. . " Suponho que ele se sentiu da mesma maneira com o sinal de mais, daí a necessidade de escapar dele para usá-lo como um metacaractere. É fácil ser enganado por isso.

Em sed você precisa escapar +, ?, |, (, e ). ou use -r para usar regex estendido (então parece sed -r -e "s/[[:space:]]\+/ /g"oused -re "s/[[:space:]]\+/ /g"

Estrela do Mar
fonte
Isso remove as guias também? Você pode explicar por que usa em \+vez de apenas +?
Zulakis 23/09/12
OK, eu entendo. [[: espaço:]] é igual a [\ t \ r \ n \ v \ f]. Mas você pode, por favor, explicar por que você usa\+
Zulakis 23/09/12
3
[[: space:]] é equivalente a '\ s', portanto a versão mais curta é "s / \ s \ + / / g"
3molo
2
Expressões regulares básicas usam uma barra invertida antes de um sinal de mais quando usadas para significar "um ou mais caracteres ou grupos anteriores", fonte developer.apple.com/library/mac/#documentation/opensource/… .
3molo
Ahh, eu entendo! Eu não sabia que havia versões diferentes de regex. Obrigado
Zulakis
6

Você pode usar a opção -s("squeeze") de tr:

$ tr -s '[:blank:]' <<< 'test.de.          1547    IN      SOA     ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600'
test.de. 1547 IN SOA ns1.test.de. dnsmaster.test.de. 2012090701 900 1000 6000 600

A [:blank:]classe de caracteres compreende espaços e tabulações.

Benjamin W.
fonte
-2

Eu gosto de usar o seguinte alias para o bash. Com base no que os outros escreveram, use o sed para pesquisar e substituir vários espaços por um único espaço. Isso ajuda a obter resultados consistentes do corte. No final, eu o passo através do sed mais uma vez para mudar o espaço para a guia, para que seja mais fácil de ler.

alias ll='ls -lh | sed "s/ \+/ /g" | cut -f5,9 -d" " | sed "s/ /\t/g"'
CNS Security miked
fonte
Como isso responde à pergunta?
quer