2017-10-10 1 views
1

Je suis un nouveau venu pour les expressions régulières, alors s'il vous plaît ours avec moi.R: Supprimer les points dans le texte, mais pas ceux marquant les points décimaux

J'ai une chaîne comme ceci:

txt1 <- 'a,b,a.b,a.,1,2,1.2,1.,.,11,222,11.222,11.' 

Imaginez qu'il est d'une .csv et chaque cellule est séparée par « ». Maintenant, je voudrais supprimer tous les '.' sauf ceux marquant les points décimaux. En cette fin, je voudrais finir avec quelque chose comme ceci:

txt2 <- 'a,b,ab,a,1,2,1.2,1,,11,222,11.222,11' 

J'ai essayé les codes suivants:

txt2 <- gsub(pattern = '[^a-z0-9,(\\d\\.\\d)]', replacement = '', text = txt1) 
txt2 <- gsub(pattern = '[^a-z0-9,|(\\d\\.\\d)]', replacement = '', text = txt1) 

Mais ni œuvres, à la fois le retour

> print(txt2) 
[1] "a,b,a.b,a.,1,2,1.2,1.,.,11,222,11.222,11." 

Une idée de comment je pourrais corriger mes codes? Merci!

Répondre

0

La clé est d'utiliser le lookbehind négatif ?<! et préanalyse négative ?!

> txt1 <- 'a,b,a.b,a.,1,2,1.2,1.,.,11,222,11.222,11.' 
> txt2 <- gsub(pattern='((?<![0-9])\\.)|(\\.(?![0-9]))', replacement='', x=txt1, perl=TRUE) 
> txt2 
[1] "a,b,ab,a,1,2,1.2,1,,11,222,11.222,11" 

Ce modèle matchs une période \\. qui a procédé par un caractère non 0-9 ou une période qui est suivi d'un caractère qui n'est pas 0-9. Vous devez définir perl=TRUE pour que R reconnaisse le lookbehind et le lookahead.

Cela va couper les caractères de la période initiale, ainsi '.2' deviendra '2'. Si ce n'est pas voulu, le lookbehind doit être (?<![0-9,]).

+0

Quel est le but de mettre '\ .' dans un groupe de capture ici? – CAustin

+0

Il n'y a pas besoin de lookbehind, voir ci-dessus deux réponses. –

+0

Merci beaucoup pour l'explication détaillée. C'est très utile! – Xiangyu

1

Vous pouvez utiliser la fonction de recherche négative. Faites correspondre \.(?!\d) et remplacez-le par rien.

https://regex101.com/r/LNHYOY/1

+0

Merci beaucoup pour la réponse. Le lien est extrêmement utile! – Xiangyu

+0

Voici une question de suivi que j'espère que vous aimeriez également répondre. Puisque les crochets '()' ne sont pas reconnus dans une liste '[]', comment puis-je coder pour reconnaître quelque chose qui n'est pas dans un groupe? Est-ce que '(?! (Le groupe))' est le seul moyen? – Xiangyu

+0

Parlez-vous d'un moyen d'annuler une chaîne entière, de la même manière que [^ abc] 'annule les caractères individuels a, b et c? Il n'y a aucun moyen de reproduire exactement la façon dont cela fonctionne, mais un lookahead négatif (en utilisant '(?! ...)' comme dans la réponse ci-dessus) peut être utilisé pour obtenir quelque chose de proche. – CAustin

0

Lookahead négatif (comme suggéré par @ CAustin) semble être le plus élégant et concis.

Puisque aucune des solutions ci-dessus vous donne le code R réelle, la voici:

txt2 <- gsub("\\.(?!\\d)", "", txt1, perl = TRUE) 
[1] "a,b,ab,a,1,2,1.2,1,,11,222,11.222,11" 
+0

Merci pour la réponse! – Xiangyu