Faire correspondre uniquement la première occurrence d'une ligne avec Regex

40

Je suis complètement nouveau pour regex et j'apprécierais grandement toute aide.

La tâche est simple. J'ai un fichier CSV avec des enregistrements qui se lisent comme ceci:

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

Je voudrais remplacer la première virgule par un espace et laisser le reste des virgules intact, pour chaque ligne. Existe-t-il une expression regex qui ne correspond à la première virgule?

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

cows_eat_hay
la source
quel outil utilisez-vous? (sed, perl, awk, autre chose?)
Mat le
Bloc de texte

Réponses:

49

Le motif correspondant pourrait être:

^([^,]+),

Cela signifie

^        starts with
[^,]     anything but a comma
+        repeated one or more times (use * (means zero or more) if the first field can be empty)
([^,]+)  remember that part
,        followed by a comma

Dans Perl, par exemple, la correspondance complète et son remplacement ressemblent à ceci:

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

La pièce de remplacement prend simplement tout ce qui correspond et le remplace par le premier bloc mémorisé et ajoute un espace. Le coma est "supprimé" car il ne fait pas partie du premier groupe de capture.

Tapis
la source
Impressionnant! Merci Mat, ça a très bien fonctionné. En fait, cela ne fonctionnait pas dans Textpad (je pense que leur expression régulière est limitée), alors j'ai fini par télécharger PowerGrep, et j'ai utilisé la recherche et le remplacement par l'expression que vous avez fournie et cela a très bien fonctionné. Merci également pour la bonne explication, cela aide à comprendre ce qui se passe.
cows_eat_hay
7
s/,/ /

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

Mork
la source
1
Est-ce vraiment la syntaxe de recherche et remplacement du Textpad?
Daniel Beck
1
Ceci est une syntaxe de sed, perlet quelques autres outils.
Pabouk
3

Cela devrait correspondre uniquement le premier numéro et la virgule: ^(\d{5}),. Si vous souhaitez engloutir tout le reste de la ligne, changez la regex en ceci:^(\d{5}),(.*)$

alex
la source
Cela a également fait l'affaire. En fait, j'ai finalement utilisé la solution de Mat, mais j'ai également testé la vôtre et cela fonctionne. Merci pour l'aide!
cows_eat_hay
Pourquoi \d{5}et pas [^,]*? Cela serait au moins plus générique.
Justin CB
2

Une solution plus élégante consiste à utiliser la correspondance paresseuse:

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

cela 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 seront remplacés par group ( \1) et un caractère d'espace.

ghost28147
la source
Notez que cela ne correspond pas à une ligne qui ne contient pas de virgule (une seule valeur sur une ligne). Associer n'importe lequel * pourrait être meilleur qu'un +alorss/^(.*?),/\1 /
Jeff Puckett
Vous pouvez également faire s/^([^,]*),/\1 /, ce qui correspond au début, tout ce qui n'est pas une virgule, puis une virgule. Aussi, ne savez-vous pas que s//cela ne change rien?
Justin CB
1

TextPad a toujours eu la possibilité d'utiliser la notation posix, mais vous devez modifier 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" entre les parenthèses ouvrantes et fermantes:

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

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

Avec onglet

\1\t

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

\ (est une "parenthèse d'échappement" 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 pouvez omettre les crochets, mais personne ne pourra 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

La commande search and replace recherche donc un ou plusieurs chiffres, suivis d'un espace. Ensuite, tout cela est remplacé par le même groupe de chiffres suivi d'un onglet.

Je ne pense pas qu'il soit possible de trouver simplement "un espace après 5 chiffres" afin de pouvoir simplement remplacer cet espace sans toucher aux chiffres. Vous devez trouver les 5 chiffres (la première chaîne) suivis de l'espace (la deuxième chaîne). Ensuite, bien que cela semble redondant ou fastidieux, REMPLACEZ la chaîne originale de 5 chiffres par ITSELF, suivie de la tabulation (la deuxième chaîne).

Tous ceux qui le savent oublient que les débutants n’en ont aucune idée. C'est pourquoi je vous l'explique, mon ami.

Ed Poor Math Tutor et programmeur à la retraite, New York City

utilisateur423655
la source