2 votes

Regex : Remplacer un nombre arbitraire d'espaces blancs par le même nombre d'un autre caractère

Ce que j'essaie de faire, c'est de prendre une liste formatée comme une table des matières et de remplacer les espaces (caractères d'espacement simples, pas les tabulations) entre les textes de gauche et de droite par des points, en ne conservant que les deux caractères d'espacement les plus éloignés.

Donc spécifiquement, je veux prendre une liste comme celle-ci :

foo        url1
foobar     url2
foo bar    url3

Et convertissez-le en ceci :

foo ...... url1
foobar ... url2
foo bar .. url3

J'utilise le IDE Eclipse pour avoir édité mon texte. Je ne suis pas familier avec les différents moteurs de regex, mais je suppose qu'il utilise soit Jakarta Regexp, soit java.util.regex (que j'ai cherché sur Wikipedia).

Je peux capturer les caractères d'espacement dans l'élément Trouvez en utilisant " ( +) ", mais je ne sais pas comment les convertir en un même nombre de points dans le format Remplacer par champ.

J'ai fait quelques recherches sur Google et je suis tombé sur cette question (c'est là que j'ai appris le " ( +) syntaxe "). Il semble que ce soit la même question ou une question similaire à la mienne. Mais soit je n'ai pas trouvé ma réponse, soit je n'ai tout simplement pas compris les réponses données.

2voto

Toto Points 14447

Vous pouvez le faire avec Notepad++

  • Ctrl + H
  • Trouvez quoi : (?<!\S) (?= )
  • Remplacer par : .
  • vérifier Wrap around
  • vérifier l'expression régulière
  • Replace all

Explication :

(?<!    : Start negative lookbehind, make sure we have not
  \S    : a non-space character
)       : end lookbehind
        : a space
(?=     : start lookahead, make sure we have
        : a space
)       : en lookahead

Remplacement :

.       : a dot

Résultat pour l'exemple donné :

foo ...... url1
foobar ... url2
foo bar .. url3

1voto

Scott Points 20468

La question indique explicitement que les titres contiendront des espaces.  Pour des raisons de sécurité, je suppose que les titres peuvent contenir des points ; par exemple, "L'histoire de 3.14159" ou "La découverte du Dr. Doolittle".  Mes réponses supposent qu'il y a algunos caractère qui n'apparaîtra jamais dans la table des matières ; Plus précisément, ils supposent que c'est @ .  Si vous avez @ dans votre table, remplacez-le par un caractère qui n'apparaît jamais (par exemple # , ^ , _ , | etc.).  Si vous utilisez vraiment tous les caractères ASCII, il vous faudra peut-être utiliser une séquence de caractères, telle que <@> .

Trois façons de le faire avec sed :

Boucle :

sed 's/\(.*\)\( \)/\1@\2/; :loop; s/  @/ @./; t loop; s/@//'
  • s/\(.*\)\( \)/\1@\2/ trouve le dernier espace sur la ligne et insère un @ avant elle.
  • :loop est une étiquette, comme une borne kilométrique.
  • s/ @/ @./ (c'est s/@/@./ pour éviter toute ambiguïté) dit, s'il y a deux espaces avant le @ , remplacez-les par . (espace et point), et déplacez le @ entre eux.
  • t loop dit, si la substitution ci-dessus a réussi, revenir à la :loop marqueur et répétez.  Sinon, continuez à
  • s/@// qui supprime le @ .

Ainsi, le foo bar dans votre tableau seront traitées comme suit :

Initial value:          foo bar    url3
s/\\(.\*\\)\\( \\)/\\1@\\2/    foo bar   @ url3
s/  @/ @./              foo bar  @. url3
s/  @/ @./              foo bar @.. url3
s/  @/ @./              foo bar @.. url3        _(Substitution fails, so don’t loop)_
s/@//                   foo bar .. url3
Final output:           foo bar .. url3

Des chiffres écrasants :

sed 's/\(.*\)\( \)/\1@@@@@@@@@@@@@@@@@@@@\2/; s/ [ @]\{20\}/ /; s/@/./g'
  • s/\(.*\)\( \)/\1@@@@@@@@@@@@@@@@@@@@\2/ est très similaire à la première s dans la première solution ; elle trouve le dernier espace sur la ligne et insère une chaîne de 20 @ les caractères qui le précèdent.  Cela devrait être un nombre qui est au moins aussi grand que le nombre maximum de points que vous devrez jamais insérer sur une ligne, par exemple 80.  Gérer une chaîne de 80 @ les personnages seraient gênants ; vous pourriez le remplacer par
    • s/\(.*\)\( \)/\1<@><@><@><@><@>\2/; s/<@>/@@@@@@@@/g qui insère une chaîne de cinq <@> séquences, et remplace ensuite chacune d'entre elles par une chaîne de 16 @ des personnages, ce qui donne 5×16=80 @ des personnages.
  • s/ [ @]\{20\}/ / trouve une chaîne de 20 caractères consécutifs qui sont soit un espace, soit un @ précédé d'un espace, et le remplace par le seul espace précédent.  Remplacer 20 avec le numéro de l'étape précédente.
  • s/@/./g remplace chaque @ avec un point.

Ainsi, le foo dans votre tableau seront traitées comme suit :

Initial value:                  foo        url1
s/\(.*\)\( \)/\1@@@@...@@@@\2/  foo       @@@@@@@@@@@@@@@@@@@@ url1
s/ [ @]\{20\}/ /                   _[remove]
                                foo @@@@@@ url1
s/@/./g                         foo ...... url1

Utilisez l'"espace de maintien" :

sed 's/.*[^ ] /&@/; h; s/ /./g; s/\(\.*\)\./\1 /; x; G; s/@.*@//'
  • s/.*[^ ] /&@/ es similaire aux commandes précédentes ; il trouve la fin du titre - pour être précis, le dernier endroit où un caractère non-blanc est suivi d'un espace - et insère un @ après elle.
  • h copie la ligne dans l'espace d'attente.
  • s/ /./g remplace tous les espaces de la ligne par des points.
  • s/\(\.*\)\./\1 / remplace le dernier point par un espace.  (Cela devra changer si l'URL peut contenir des points, ce qui, je suppose, est probable).
  • x échange l'espace du motif et l'espace du maintien.
  • G ajoute l'espace de maintien à l'espace du motif.  Nous avons maintenant, essentiellement, deux copies de la ligne.
  • s/@.*@// conserve la première partie de la première copie et la seconde partie de la seconde copie, en se débarrassant de ce qui se trouve au milieu.

    Initial value: foo bar url3

                      Pattern space                            Hold space

    s/.[^ ] /&@/ foo bar @ url3 h foo bar @ url3 foo bar @ url3 s/ /./g foo.bar.@...url3 foo bar @ url3 s/(.)./\1 / foo.bar.@.. url3 foo bar @ url3 x foo bar @ url3 foo.bar.@.. url3 G foo bar @ url3 foo.bar.@.. url3 foo.bar.@.. url3 s/@.*@// foo bar .. url3 foo.bar.@.. url3

    Final output: foo bar .. url3

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X