Comment faire correspondre les espaces dans sed?

218

Comment puis-je assortir les espaces dans sed? Dans mes données, je souhaite faire correspondre tous les 3 + espaces blancs suivants (espace de tabulation) et les remplacer par 2 espaces. Comment cela peut-il être fait?

Peter Smit
la source

Réponses:

226

La classe de caractères \scorrespondra aux caractères d'espacement <tab>et <space>.

Par exemple:

$ sed -e "s/\s\{3,\}/  /g" inputFile

remplacera chaque séquence d’au moins 3 espaces blancs par deux espaces.


REMARQUE : Pour la conformité POSIX, utilisez la classe de caractères à la [[:space:]]place de \s, car cette dernière est une extension GNU sed. Voir les spécifications POSIX pour sed et BRE

mrucci
la source
5
aha! C'est l'interrupteur manquant qui m'a attiré.
séquoia mcdowell
25
J'ai également dû ajouter le paramètre -r qui permet aux expressions rationnelles étendues de faire en sorte que sed reconnaisse "\ s" comme étant un espace.
HUB
39
Avec Apple, sedje devais utiliser [[:space:]]car \scela ne fonctionnait pas pour moi. Peut \s- être est une extension GNU sed ?
Jared Beck
2
@ JaredBeck merci, était à court d'idées pourquoi mon regex simple ne fonctionnait pas .. Ceci est boiteux, je pensais que était standard regex étendu .. Aussi -r ne fonctionne pas et -E n'a pas squaté
Karthik T
3
Au lieu d' [[:space:]un, vous pouvez utiliser [[:blank:]]ce qui ne correspond qu'aux onglets et espaces horizontaux (mais pas aux nouvelles lignes, aux onglets verticaux, etc.).
Stefanct
67

Cela fonctionne sur MacOS 10.8:

sed -E "s/[[:space:]]+/ /g"
Quelques idées
la source
2
savez-vous si cela fonctionne sur toutes les distributions Linux?
amphibient
2
De manière générale, GNU sed n'aura pas -E. Sur la page de manuel BSD sed: "Les options -E, -a et -i sont des extensions FreeBSD non standard et peuvent ne pas être disponibles sur d'autres systèmes d'exploitation."
Brad Koch
1
Pourquoi avez-vous besoin du drapeau -E pour l'opérateur +? La plupart des expressions conviendraient probablement avec * au lieu de cela, alors cela fonctionnerait sur d'autres plateformes.
Samuel
5
@Samuel Si vous utilisez *, la regex correspondra à zéro ou plusieurs espaces, et vous obtiendrez un espace entre chaque caractère et un espace à chaque fin de chaque ligne. Si vous n'avez pas l'indicateur -E, vous voulez sed "s/[[:space:]]\+/ /g"faire correspondre un ou plusieurs espaces.
jbo5112
1
FWIW, le serveur sed de NetBSD prend également en charge le -Edrapeau.
mcandre
13

Certaines versions plus anciennes de sed peuvent ne pas reconnaître \ s comme un jeton de correspondance d’espace. Dans ce cas, vous pouvez faire correspondre une séquence d'un ou plusieurs espaces et onglets avec '[XZ] [XZ] *' où X est un espace et Z est un onglet.

Marnix A. van Ammers
la source
1
Donc, pour le besoin particulier ici, avec un ancien sed, vous pouvez faire ceci: $ sed 's / [XZ] [XZ] [XZ] [XZ] * / / g' où X est un onglet et Z un espace.
Marnix A. van Ammers le
10
sed 's/[ \t]*/"space or tab"/'
Zac
la source
2
Est-ce que cela fonctionne avec n'importe quelle version de sedn'importe quel système? Si ce n'est pas le cas, il pourrait être intéressant de préciser où cela fonctionne de la même manière que les autres réponses, afin que nous connaissions les limites et où cela pourrait ne pas avoir le résultat escompté.
Mokubai
2
Cette RE est ce que j'utilise pour faire correspondre les espaces. Il est plus simple que les classes de personnage de faire correspondre une tabulation ou un espace. Il utilise uniquement les conventions les plus élémentaires des expressions régulières. Il devrait donc fonctionner n'importe où avec une implémentation fonctionnelle d'expressions régulières.
Nate
3
Sur Mac 10.9.5, cela correspond aux espaces et à 't'. J'ai utilisé ci-dessus Michael Douma pour faire correspondre les caractères d'espaces (cela fonctionne aussi avec -e).
Alien Life Form
Ne fonctionne pas correctement sur mon système SUSE. Il correspond à la première place sur la ligne où il y a zéro espace ou plus, ce qui est avant le premier caractère. Je doute que ce soit la fonction prévue, et n'était certainement pas le cas d'utilisation demandé. Je crois que vous voulez changer le '*' pour '\ +' (ou '\ {3, \}' selon la question) et peut-être mettre ag à la fin de la commande sed pour correspondre à toutes les occurrences du motif. Remplacer [\ t] par [[: space:]] peut également être souhaitable, au cas où il y aurait autre chose pour les espaces dans la ligne.
jbo5112