sed convertit 4 espaces en 2

14

Comment convertir 4 espaces en 2 espaces avec sed? C'est possible?

J'ai trouvé cela mais il convertit les tabulations en espaces:

sed -r ':f; s|^(\t*)\s{4}|\1\t|g; t f' file

chrisjlee
la source

Réponses:

13

Le script que vous avez publié convertit 4 * n espaces en n tabulations, uniquement si ces espaces sont précédés uniquement par des tabulations.

Si vous souhaitez remplacer 4 espaces par 2 espaces, mais uniquement en retrait, alors qu'il est possible de le faire avec sed, je recommande plutôt Perl.

perl -pe 's{^((?: {4})*)}{" " x (2*length($1)/4)}e' file

Dans sed:

sed -e 's/^/~/' -e ': r' -e 's/^\( *\)~    /\1  ~/' -e 't r' -e 's/~//' file

Vous voudrez peut-être utiliser à la indentplace.

Gilles 'SO- arrête d'être méchant'
la source
J'ai euNested quantifiers in regex; marked by <-- HERE in m/^( {4}* <-- HERE )/ at -e line 1.
eddygeek
1
@eddygeek Oh, en effet, cela et quelques autres bugs. J'ai remplacé le gobbledygook par du code perl réel.
Gilles 'SO- arrête d'être méchant'
5

La méthode simple ne fonctionne-t-elle pas:

sed -r 's/ {4}/  /g'

Sinon, postez une entrée là où elle échoue.

Thor
la source
1
Ce n'est pas restitué au début de la ligne. Si vous l'ancrez là-bas, cela ne fonctionnera pas pour plusieurs correspondances. Nous sommes donc sur unix.stackexchange.com/a/375200/259620 ci-dessous.
geek-merlin
Cela ne fonctionne pas si vous avez une combinaison de 2 espaces et 4 espaces, car deux indentations de deux seront comptées comme quatre ...
Matt Fletcher
@aexl: Ce n'était pas une exigence du PO
Thor
@mattfletcher: la question était de remplacer 4 espaces par 2, donc je ne vois pas votre point
Thor
4

Si seuls les espaces de début doivent être convertis:

sed 'h;s/[^ ].*//;s/    /  /g;G;s/\n *//'

Avec commentaires:

sed '
  h; # save a copy of the pattern space (filled with the current line)
     # onto the hold space
  s/[^ ].*//; # remove everything starting with the first non-space
              # from the pattern space. That leaves the leading space
              # characters
  s/    /  /g; # substitute every sequence of 4 spaces with 2.
  G; # append a newline and the hold space (the saved original line) to
     # the pattern space.
  s/\n *//; # remove that newline and the indentation of the original
            # line that follows it'

Regardez également le 'ts'réglage et la :retabcommande de vim

Stéphane Chazelas
la source
En utilisant votre solution vim, existe-t-il un moyen de modifier plusieurs fichiers comme ça avec vim? Sinon, je suppose que je devrais créer une macro?
chrisjlee
Notez que 'ts'et :retabne sont pas des solutions à la question, mais sont liés et peuvent aider à atteindre votre objectif global. Vous pouvez le faire vim -- *.c, :set ts=...puis :argdo retabou ou :argdo retab!. Voir également l' 'sw'option et les capacités de mise en retrait de vim.
Stéphane Chazelas
2
sed 's/^\( \+\)\1\1\1/\1\1/' file

Il fonctionne en divisant les espaces de tête en quatre instances du même groupe (ils sont donc tous égaux), puis en les remplaçant par seulement deux instances du groupe.

Mal
la source
Comment cela améliore-t-il les solutions existantes?
Philippos
1
Il préserve les espaces impairs, n'affecte que les espaces blancs de tête, ne nécessite pas le drapeau global, peut être facilement modifié pour gérer n'importe quel nombre d'espaces (ou tabulations) des deux côtés du remplacement et n'utilise pas de commandes sed plus complexes qui peut être rebutant pour les utilisateurs plus occasionnels. Comme pour beaucoup de choses, que ce soit une amélioration est assez subjectif, mais pour moi: trouver cela dans un script serait beaucoup plus facile à trouver rapidement que certaines des autres solutions répertoriées.
Mal
Intéressant. Content d'avoir demandé. Habituellement, les références arrières sont considérées comme mauvaises plutôt que comme le drapeau mondial. Mais vous pourriez facilement réaliser la même chose avec un script plus portable (en évitant \+). Je vous remercie.
Philippos
1
sed 's/    \{2,4\}\( \{0,1\}[^ ].*\)*/  \1/g' <input

Cela ne devrait comprimer que les séquences d'espaces en tête.

mikeserv
la source