4 votes

Séparez les chaînes en lignes sauf entre des ensembles de délimiteurs

J'ai des énoncés avec des symboles d'annotation :

utt <- c("hey girls can I ", "((v: grunts))", "!damn shit! got it", 
"I mean /yeah we saw each other at a party:/ the other day"
)

Je dois diviser utt en mots séparés sauf si les mots sont inclus entre certains délimiteurs, y compris cette classe [(/£<>°!]. Je m'en sors raisonnablement bien en utilisant un double négatif anticipé pour les utt où il n'y a qu'une seule chaîne entre les délimiteurs ; mais j'échoue à diviser correctement là où il y a plusieurs chaînes entre les délimiteurs :

library(tidyr)
library(dplyr)
data.frame(utt2) %>%
  separate_rows(utt, sep = "(?!.*[(/£<>°!].*)\\s(?!.*[)/£<>°!])")
# A tibble: 9 × 1
  utt2                                        

1 hey girls can I                
2 ((v: grunts))                               
3 !damn shit!                                 
4 got                                         
5 it                                          
6 I mean /yeah we saw each other at a party:/
7 the                                         
8 other                                       
9 day 

Le résultat attendu serait :

1 hey girls 
2 can
3 I
4                
5 ((v: grunts))                               
6 !damn shit!                                 
7 got                                         
8 it                                          
9 I
10 mean 
11 /yeah we saw each other at a party:/
12 the                                         
13 other                                       
14 day

5voto

Wiktor Stribiżew Points 100073

Vous pouvez utiliser

data.frame(utt2) %>% separate_rows(utt2, sep = "(?:([/£°!]).*?\\1|\\([^()]*\\)|<[^<>]*>)(*SKIP)(*F)|\\s+")

Consultez la démonstration regex.

Notez que dans votre cas, il y a des caractères appariés (comme ( et ), < et >) et des caractères non appariés (comme , £). Ils nécessitent une manipulation différente reflétée dans le modèle.

Détails:

  • (?:([/£°!]).*?\\1|\\([^()]*\\)|<[^<>]*>)(*SKIP)(*F) correspond à
    • ([/£°!]).*?\1| - un caractère /, , , £, ° ou ! capturé dans le Groupe 1, puis tout caractère autre que des sauts de ligne aussi peu que possible (voir .*?) et ensuite le même caractère que celui capturé dans le Groupe 1
    • \([^()]*\)| - (, zéro ou plusieurs caractères autres que ( et ) puis un caractère ), ou
    • <[^<>]*> - <, zéro ou plusieurs caractères autres que < et > puis un caractère >
    • (*SKIP)(*F) - sauter le texte correspondant et recommencer une nouvelle recherche à partir de la position d'échec
  • | - ou
  • \s+ - un ou plusieurs espaces blancs dans un autre contexte.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X