60 votes

Correspondance uniquement avec la première occurrence dans une ligne avec Regex

Je suis complètement nouveau avec les regex et j'apprécierais vraiment toute aide.

La tâche est simple. J'ai un fichier CSV avec des enregistrements qui ressemblent à ceci :

12345,67890,12345,67890
12345,67890,12345,67890
12345,67890,12345,67890
12345,67890,12345,67890
12345,67890,12345,67890

J'aimerais remplacer la première virgule par un espace et laisser les autres virgules intactes, pour chaque ligne. Y a-t-il une expression regex qui ne correspondra qu'à la première virgule ?

J'ai essayé ceci : ^.....,. Cela correspond à la virgule, cependant, cela correspond également à toute la longueur de la chaîne précédant la virgule, donc si j'essaie de remplacer cela par un espace, tous les chiffres sont également supprimés.

0 votes

Quel outil utilisez-vous? (sed, perl, awk, autre chose?)

2 votes

Textpad (Windows)

82voto

givp Points 798

Le motif de correspondance pourrait être :

^([^,]+),

Cela signifie :

^        commence par
[^,]     n'importe quoi sauf une virgule
+        répété une ou plusieurs fois (utilisez * (signifie zéro ou plusieurs) si le premier champ peut être vide)
([^,]+)  se souvenir de cette partie
,        suivi d'une virgule

Par exemple, en perl, la correspondance et le remplacement complets ressembleraient à :

s/^([^,]+),/\1 /

La partie de remplacement prend simplement l'ensemble de la chaîne qui correspond et la remplace par le premier bloc que vous avez mémorisé et ajoute un espace. La virgule est "supprimée" car elle ne se trouve pas dans le premier groupe de capture.

1 votes

Génial! Merci Mat, ça a très bien fonctionné. En fait, ça ne marchait pas dans Textpad (je pense que leur regex est limité), donc j'ai fini par télécharger PowerGrep et utilisé la recherche et le remplacement avec l'expression que vous avez fournie et ça a très bien fonctionné. Merci aussi pour l'explication détaillée, ça aide à comprendre ce qui se passe.

9voto

Mork Points 91
s/,/ /

Ceci, par défaut (c'est-à-dire sans l'option g), remplace uniquement la première correspondance.

1 votes

Est-ce vraiment la syntaxe de recherche et de remplacement de Textpad?

2 votes

Voici une syntaxe de sed, perl et d'autres outils.

3voto

user7375 Points 569

Cela devrait correspondre uniquement au premier nombre et à la virgule : ^(\d{5}),. Si vous souhaitez récupérer tout le reste de la ligne, modifiez l'expression régulière pour cela : ^(\d{5}),(.*)$

0 votes

Cela a également fonctionné. J'ai finalement utilisé la solution de Mat mais j'ai aussi testé la vôtre et ça marche. Merci pour l'aide!

0 votes

Pourquoi \d{5} et pas [^,]*? Ce serait au moins plus générique.

3voto

ghost28147 Points 131

Une solution plus élégante est d'utiliser une correspondance paresseuse :

s/^(.+?),/\1 /

qui regroupera les caractères en se déplaçant du début de la chaîne (^) vers la fin d'un caractère (.+?) à chaque étape jusqu'à ce qu'il trouve le premier signe de virgule. Tout ce groupe ainsi que la première occurrence de virgule sera remplacé par le groupe (\1) et un caractère d'espace.

0 votes

Notez que cela ne correspondra pas à une ligne qui ne contient pas de virgule (une seule valeur sur une ligne). Mettre en correspondance n'importe quel * serait peut-être mieux que + donc s/^(.*?),/\1 /

0 votes

Tu pourrais aussi faire s/^([^,]*),/\1 /, ce qui correspondrait au début, à n'importe quoi sauf une virgule, puis une virgule. De plus, ne sais-tu pas que s// ne change rien s'il n'y a pas de correspondance ?

1voto

user423655 Points 11

TextPad a toujours eu la possibilité d'utiliser la notation posix, mais vous devez changer les paramètres dans une boîte de dialogue différente. Pour utiliser les paramètres par défaut de TextPad pour les expressions régulières, vous devez "échapper" les parenthèses ouvrantes et fermantes:

Remplacez l'espace après le code postal à 5 chiffres, au début de chaque ligne

^\([0-9]+\)[ ]

Par une tabulation

\1\t

Comme ci-dessus, le ^ signifie le début de la ligne

\( est une "parenthèse échappée" et marque le début de la première expression de recherche, c'est-à-dire les cinq chiffres

[0-9]+ signifie un ou plusieurs chiffres (pas seulement des codes postaux à 5 chiffres)

\) est une autre "parenthèse échappée" pour marquer la fin de la première expression de recherche

[ ] est juste un caractère espace (vous pourriez omettre les crochets, mais alors personne ne pourrait le voir sur cette page web :-)

Dans l'expression de remplacement

\1 est la première expression de recherche, la partie entre parenthèses ci-dessus (un ou plusieurs chiffres)

\t est un caractère de tabulation

Donc, la commande de recherche et de remplacement recherche un ou plusieurs chiffres, suivis d'un espace. Ensuite, elle remplace tout cela par le même groupe de chiffres suivi d'une tabulation.

Je ne pense pas qu'il y ait un moyen simple de trouver simplement "un espace qui vient après 5 chiffres" pour que vous puissiez simplement remplacer l'espace sans toucher aux chiffres. Vous devez trouver les 5 chiffres (le premier groupe) suivis de l'espace (le deuxième groupe). Ensuite, bien que cela semble redondant ou fastidieux, REMPLACEZ la chaîne originale de 5 chiffres par ELLE-MÊME, suivie de la tabulation (le deuxième groupe).

Tout le monde qui connaît cela oublie que les débutants n'ont aucune idée de cela. C'est pourquoi je vous l'explique en détail, mon ami.

Ed Poor Tuteur en mathématiques et programmeur informatique à la retraite New York City

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