sed remplace tous les onglets et espaces par un seul espace

23

J'ai une chaîne comme celle-ci:

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

maintenant, je veux remplacer tous les onglets / espaces entre les enregistrements par un seul espace afin que je puisse facilement l'utiliser avec cut -d " "

J'ai essayé ce qui suit:

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

et diverses variantes, mais n'a pas pu le faire fonctionner. Des idées?

Zulakis
la source
Essayez: sed -r -e "s / [\ t \] + / / g"
RJS
Votre option de cutsupport -w?
Kondybas

Réponses:

40

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

Voici une explication:

[   # 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).

Pour votre remplacement, vous souhaitez uniquement insérer un espace. [:space:]ne fonctionnera pas là car c'est une abréviation pour une classe de personnage et le moteur regex ne saurait pas quel personnage y mettre.

Le +doit être échappé dans l'expression régulière, car avec le moteur d'expression régulière de sed +est un caractère normal alors qu'il \+s'agit d'un métacaractère pour «un ou plusieurs». À la page 86 de Mastering Regular Expressions , Jeffrey Friedl mentionne dans une note de bas de page que ed et grep ont utilisé des parenthèses échappées parce que "Ken Thompson pensait que les expressions régulières seraient utilisées pour travailler principalement avec le code C, où la nécessité de faire correspondre les parenthèses brutes serait plus courante que les références arrières . " Je suppose qu'il ressentait la même chose à propos du signe plus, d'où la nécessité de lui échapper pour l'utiliser comme métacaractère. Il est facile de se faire tromper par cela.

En vous sed aurez besoin d'échapper +, ?, |, (et ). ou utilisez -r pour utiliser l'expression régulière étendue (il ressemble alors à sed -r -e "s/[[:space:]]\+/ /g"oused -re "s/[[:space:]]\+/ /g"

Étoile de mer
la source
Est-ce que cela supprime également les onglets? Pouvez-vous expliquer pourquoi vous utilisez \+au lieu de juste +?
Zulakis
Ok, je comprends. [[: space:]] est égal à [\ t \ r \ n \ v \ f]. Mais pouvez-vous s'il vous plaît expliquer pourquoi vous utilisez\+
Zulakis
3
[[: space:]] est équivalent à '\ s', donc la version plus courte est "s / \ s \ + / / g"
3molo
2
Les expressions régulières de base utilisent une barre oblique inverse avant un signe plus lorsqu'elles sont utilisées pour signifier «un ou plusieurs des caractères ou groupes précédents», source developer.apple.com/library/mac/#documentation/opensource/… .
3molo
Ahh, je comprends! Je ne savais pas qu'il existait différentes versions de regex. Merci
Zulakis
6

Vous pouvez utiliser l' -soption ("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

La [:blank:]classe de caractères comprend à la fois des espaces et des tabulations.

Benjamin W.
la source
-2

J'aime utiliser l'alias suivant pour bash. En s'appuyant sur ce que les autres ont écrit, utilisez sed pour rechercher et remplacer plusieurs espaces par un seul espace. Cela permet d'obtenir des résultats cohérents de coupe. À la fin, je l'ai parcouru une fois de plus dans sed pour changer l'espace en tab afin qu'il soit plus facile à lire.

alias ll='ls -lh | sed "s/ \+/ /g" | cut -f5,9 -d" " | sed "s/ /\t/g"'
CNS Security miked
la source
Comment cela répond-il à la question?
Tonin