Измените регулярное выражение с PRCE на ICU для соответствия использованию stringr - PullRequest
0 голосов
/ 03 апреля 2020

Недавно я задал вопрос о создании сложного регулярного выражения для разбиения строки ( здесь ). Я работал с базой R, поэтому все работало нормально. Тем не менее, теперь я хочу использовать то же выражение в другой части моего кода, которая следует за «окружением» (я хочу использовать tidyr::separate_rows), и оно не работает, потому что мой шаблон PRCE и stringr использует только библиотеку ICU.

Воспроизводимый пример:

vec <- c("'01'", "'01' '02'", 
         "#bateau", "#bateau #batiment",
         "#'autres 32'", "#'autres 32' #'batiment 30'", "#'autres 32' #'batiment 30' #'contenu 31'",
         "#'34'", "#'34' #'33' #'35'")

У меня есть предыдущая строка, которую мне нужно разбить везде, где есть пробел (), за исключением случаев, когда пробел между '. @Wiktor Stribiżew любезно ответили на мой вопрос и дали мне этот шаблон '[^']*'(*SKIP)(*F)|\\s+, который отлично работал при вызове strsplit:

strsplit(vec, "'[^']*'(*SKIP)(*F)|\\s+", perl=TRUE)
[[1]]
[1] "'01'"

[[2]]
[1] "'01'" "'02'"

[[3]]
[1] "#bateau"

[[4]]
[1] "#bateau"   "#batiment"

[[5]]
[1] "#'autres 32'"

[[6]]
[1] "#'autres 32'"   "#'batiment 30'"

[[7]]
[1] "#'autres 32'"   "#'batiment 30'" "#'contenu 31'" 

[[8]]
[1] "#'34'"

[[9]]
[1] "#'34'" "#'33'" "#'35'"

Однако, когда я попробовал тот же шаблон в функции Tidyverse, я получил эту ошибку :

stringr::str_split(vec, "'[^']*'(*SKIP)(*F)|\\s+")
Error in stri_split_regex(string, pattern, n = n, simplify = simplify,  : 
  Syntax error in regexp pattern. (U_REGEX_RULE_SYNTAX)

Здесь , @Wiktor Stribiżew был достаточно любезен, чтобы объяснить проблему, потому что это выражение PCRE, в то время как tidyverse использует ICU

Есть ли способ заставить мое выражение работать в тидиверсе? Если нет, какое выражение будет работать? Обратите внимание, что в моем примере используется strsplit, так как проще объяснить проблему. Однако в конце я хочу использовать функцию tidyr::separate_rows, объясняющую, почему мне нужно решение, совместимое с tidyverse.

1 Ответ

1 голос
/ 04 апреля 2020

Учитывая ваш пример, вы можете просто нацелить и разделить пробелы, за которыми следует # с этим регулярным выражением \\s(?=#).

Если вам нужно что-то более гибкое, одним из решений является сначала нацеливание и замена пробелов, которые вы хотите разделить, используя ваши предыдущие регулярные выражения '[^']*'(*SKIP)(*F)|\\s+ и gsub, которые принимают регулярное выражение perl. Замените соответствующие пробелы якорем (уникальный символ или цепочка символов) и разделите строки на основе этого якоря.

vec <- c("'01'", "'01' '02'", 
         "#bateau", "#bateau #batiment",
         "#'autres 32'", "#'autres 32' #'batiment 30'", "#'autres 32' #'batiment 30' #'contenu 31'",
         "#'34'", "#'34' #'33' #'35'")

vec %>% 
  tibble(my_col = .) %>% 
  mutate(my_col = gsub("'[^']*'(*SKIP)(*F)|\\s+", "_-_", my_col, perl = TRUE)) %>% 
  separate_rows(my_col, sep = "_-_")

# A tibble: 16 x 1
   my_col        
   <chr>         
 1 '01'          
 2 '01'          
 3 '02'          
 4 #bateau       
 5 #bateau       
 6 #batiment     
 7 #'autres 32'  
 8 #'autres 32'  
 9 #'batiment 30'
10 #'autres 32'  
11 #'batiment 30'
12 #'contenu 31' 
13 #'34'         
14 #'34'         
15 #'33'         
16 #'35'
...