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

0

Ce que j'essaie de faire est de prendre une liste qui est formatée de la même manière qu'une table des matières et remplace les espaces (caractères d'espacement simples, et non de tabulations) entre les textes de gauche et de droite par des points, en ne conservant que les deux espaces les plus externes.

Donc précisément, 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 l' IDE Eclipse pour éditer mon texte. Je ne connais pas bien les différents moteurs de regex, mais je suppose qu’il utilise soit Jakarta Regexp, soit java.util.regex (que j’ai consulté sur Wikipedia).

Je peux capturer les caractères d'espacement dans le champ Rechercher à l' aide de " ( +)", mais je ne sais pas comment les convertir en autant de points dans le champ Remplacer par .

J'ai fait des recherches sur Google et je suis tombé sur cette question (c'est là que j'ai appris la " ( +)" syntaxe). Il semble que ce soit la même chose, 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.

AntumDeluge
la source
Un espace blanc ou juste des espaces? Votre expression semble ne concerner que les espaces. Alors pourquoi ne pas simplement remplacer l’espace par le personnage de votre choix?
Peu collant
Parce qu'ils ne veulent pas changer les espaces dans le titre; par exemple, “barre de foo” → “foo.bar”. En outre, ils ne veulent pas changer «foo url» en «foo ........ url»; ils veulent "foo␣ ...... url" (en gardant le premier et le dernier espace).
Scott
@ Scott Correct.
AntumDeluge
Cela ressemble à une question qui a été soulevée auparavant, et donc très probablement il a déjà été répondu ici ou sur Unix & Linux Stack Exchange . Mais je ne me souviens pas de la réponse pour le moment. J'essaierai d'y revenir plus tard quand j'aurai plus de temps, mais jusque-là, je vous suggère de rechercher notre site un peu plus difficile. Astuce: Stack Exchange a son propre moteur de recherche, mais vous obtenez parfois de meilleurs résultats en utilisant Google et en disant  site:superuser.com ou  site:unix.stackexchange.com.
Scott
J'ai fait une brève recherche (environ 15 minutes) et je n'ai trouvé aucune correspondance exacte, bien que l' utilisation de sed pour remplacer toutes les occurrences au début par un nombre correspondant de chaînes de remplacement et que les caractères de remplacement de la ligne correspondante soient proches. Étant donné que personne n'a signalé votre question comme un doublon et que vous n'avez obtenu qu'une réponse à ce jour, j'ai moi-même inventé trois réponses (la première est très similaire à l'une des questions que j'ai liées). J'espère que vous avez accès à sed.
Scott

Réponses:

1

Vous pouvez le faire avec Notepad ++

  • Ctrl+H
  • Trouver quoi: (?<!\S) (?= )
  • Remplacer par: .
  • check Enveloppez-vous
  • 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
Toto
la source
Semble intéressant. Je n'ai pas Notepad ++, donc je ne peux pas tester cela. Pouvez-vous expliquer pourquoi cela ne remplace pas le premier espace après le titre, ce qui en résulte foo.......␣url1?
Scott
@ Scott: Je suis sûr que cela fonctionne également avec SublimeText. Un espace est remplacé uniquement lorsqu'il n'y a pas de non-espace avant et un espace après.
Toto
Oh… quand il y a un espace après, et non un non-  espace avant. J'ai raté le double négatif. Ne pourriez-vous pas simplement effectuer une recherche régulière d'un espace au lieu d'une recherche négative d'un non-espace?
Scott
@Scott: Non, si j'utilise l'apparence positive (c'est-à-dire (?<=\s)), l'espace avant est obligatoire, a contrario (?<!\S) rend l'espace optionnel et c'est le cas après que le premier espace a été remplacé par un point.
Toto
Eh bien, je ne comprends toujours pas. :-( ⁠
Scott
0

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 (points); par exemple, “L’histoire de 3.14159” ou “Dr. Doolittle's Discovery ». Mes réponses supposent qu'il y a un caractère qui n'apparaîtra jamais dans la table des matières; en particulier, ils supposent que c'est @. Si vous avez @dans votre table, le remplacer par un caractère qui n'apparaît (par exemple, #, ^, _, |, etc.). Si vous utilisez réellement tous les caractères ASCII, vous devrez peut-être utiliser une séquence de caractères, comme <@>.

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.
  • :loop est une étiquette, comme un marqueur de mile.
  • s/ @/ @./(c'est-à-dire s/␣␣@/␣@./, pour la non-ambiguïté) dit, s'il y a deux espaces avant le @, les remplace par ␣.(espace et point) et déplacez-les @entre eux.
  • t loopsi la substitution ci-dessus a réussi, dit de revenir au :loopmarqueur et de répéter. Sinon, continuez à
  • s/@//, qui supprime le @.

Donc, la foo barligne dans votre table sera traitée comme suit:

Valeur initiale: foo bar url3
s / \ (. * \) \ (\) / \ 1 @ \ 2 / foo bar @ url3
s / @ / @. / foo bar @. url3
s / @ / @. / foo bar @ .. url3
s / @ / @. / foo bar @ .. url3         (La substitution échoue, ne faites pas de boucle)
s / @ // foo bar .. url3
Sortie finale: foo bar .. url3

Chiffres écrasants:

sed 's/\(.*\)\( \)/\1@@@@@@@@@@@@@@@@@@@@\2/; s/ [ @]\{20\}/ /; s/@/./g'
  • s/\(.*\)\( \)/\1@@@@@@@@@@@@@@@@@@@@\2/ est très similaire à la première ssous-commande de la première solution; il trouve le dernier espace sur la ligne et insère une chaîne de 20  @caractères devant elle. Cela devrait en fait être un nombre au moins aussi grand que le nombre maximum de points que vous devrez jamais insérer sur une seule ligne; par exemple, 80. La gestion d'une chaîne de 80  @caractères serait délicate; vous voudrez peut-être remplacer ceci par
    • s/\(.*\)\( \)/\1<@><@><@><@><@>\2/; s/<@>/@@@@@@@@/g qui insère une chaîne de cinq <@>séquences, puis remplace chacune d’elles par une chaîne de 16  @caractères, ce qui donne 5 × 16 = 80  @caractères.
  • 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. Remplacez-le 20par le numéro de l'étape précédente.
  • s/@/./gremplace chaque reste @par un point.

Donc, la fooligne dans votre table sera traitée comme suit:

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

Utilisez la "cale":

sed 's/.*[^ ] /&@/; h; s/ /./g; s/\(\.*\)\./\1 /; x; G; s/@.*@//'
  • s/.*[^ ] /&@/est similaire aux commandes précédentes; il trouve la fin du titre - pour être précis, le dernier endroit où un caractère non vide est suivi d'un espace - et insère un @après celui-ci.
  • h copie la ligne dans l'espace réservé.
  • 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 est probable, je suppose.)
  • x échange l'espace motif et l'espace d'attente.
  • Gajoute 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 deuxième copie, en éliminant le contenu au milieu.
Initial value: foo bar    url3

                      Pattern space                            Hold space
s/.*[^ ] /&@/       foo bar @   url3
h                   foo bar @   url3                        foo bar @   url3
s/ /./g             [email protected]                        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
Scott
la source