2016-01-13 5 views
0

text="stack overflow... is a popular website."Regex GSUB R различать многоточие и периоды

Я хочу, чтобы отделить знаки препинания от слов. Вывод должен быть:

"stack overflow ... is a popular website . "

Разумеется, команда gsub("\\.", " \\. ", text, fixed = FALSE) возвращает:

"stack overflow . . . is a popular website . ", потому что это не делает различий между периодами и многоточие (точек подвеса). Короче говоря, когда три текста встречаются вместе в тексте, R следует рассматривать их как единый знак препинания.

+1

'' GSUB делает ... (или 'GSUB ("([[: punct:]] +)", "\\ 1", text, fixed = FALSE) 'для любого типа пунктуации) – Cath

+0

Только периоды, а как насчет других знаков препинания? –

+0

@stribizhev все знаки препинания должны быть отделены от слов, но многоточие должно рассматриваться как единичные объекты и не разделяться в процессе – Antoine

ответ

3

Я думаю, не lookaround подход будет более эффективным и читаемым:

text="stack overflow... is a popular website." 
gsub("*[[:space:]]*(\\.+)[[:space:]]*", " \\1 ", text) 
## => [1] "stack overflow ... is a popular website . " 

См IDEONE demo

Я обновил пост, так как требуется пространство перед и после пунктуации.

[[:space:]]* вокруг (\\.+) соответствует нулю или более пробелам и (\\.+) будет соответствовать одному или нескольким периодам. (...) образуют группу захвата , значение которой хранится в пронумерованном буфере # 1, к которому мы можем получить доступ, используя обратную ссылку \1 из шаблона замены. Таким образом, \1 заменяется периодами, захваченными рисунком. Захват более эффективен, чем использование обращений, поскольку нет накладных расходов на проверку текста до/после текущей позиции.

Теперь если вам нужно обработать все знаки пунктуации, используйте [[:punct:]]:

gsub("[[:space:]]*([[:punct:]]+)[[:space:]]*", " \\1 ", text) 

См R regex help:

[:punct:]
знаки пунктуации:
! " # $ % & ' () * + , - ./: ; < = > ? @ [ \ ]^_ ` { | } ~.

Code demo:

text="Hi!stack overflow... is a popular website, I visit it every day." 
gsub("[[:space:]]*([[:punct:]]+)[[:space:]]*", " \\1 ", text) 
## => [1] "Hi ! stack overflow ... is a popular website , I visit it every day . " 

UPDATE в переносимых СЛОВ

Чтобы избежать сопоставления дефис слов, вы можете сопоставить и пропустить в -, которые окруженное словоразделами:

text="Hi!stack-overflow... is a popular website, I visit it every day." 
gsub("\\b-\\b(*SKIP)(*F)|\\s*(\\p{P}+)\\s*", " \\1 ", text, perl=T) 
## => [1] "Hi ! stack-overflow ... is a popular website , I visit it every day . " 

См. demo

+2

вы могли бы хотя бы «сохранить» мой комментарий ... ;-) – Cath

+0

@CathG: Я написал тот же комментарий перед вами, но удалил его, а ваш не правильно, так как пространство не там, где оно должно быть в замещаемом шаблоне , –

+0

Поскольку вы оставили комментарий к моему решению, это не показывает пробел после окончания '.'(Я имел ввиду посмотреть на ожидаемый вывод OP) – akrun

2

Попробуйте

gsub("(?<=\\.)$|(?<=\\w)(?=\\.)", " ", text, perl=TRUE) 
#[1] "stack overflow ... is a popular website . " 

gsub("(?<=\\.)$|(?<=\\w)(?=\\.)", " ", "aaa...", perl=TRUE) 
#[1] "aaa ... " 

gsub("(?<=\\.)(?=$|\\w)|(?<=\\w)(?=\\.)", " ", "aaa...bbb", perl=TRUE) 
#[1] "aaa ... bbb" 
+1

Большое спасибо. Было бы здорово, если бы вы могли кратко объяснить, что говорит регулярное выражение. – Antoine

+1

Это, вероятно, не самое эффективное регулярное выражение для этой задачи. –

+0

Хорошо, давайте вскочимся, я думаю, что на мой пост будет много изменений. –

3

После этой нагрузки комментариев это регулярное выражение должно быть, скорее всего, в соответствии с вашими потребностями:

(?:\b|)([.,:;!]+)(?: |\b) 

Demo

Чтобы использовать его в R обратные косые черты должны быть удвоены.

Таким образом, мы в конечном итоге с: ("(\\ +)", "\\ 1", текст, фиксированный = FALSE)

text<-c('Hi!stack-overflow... is a popular website, I visit it every day.', 
    'aaa...', 
    'AAA...B"B"B', 
    'AA .BBB #unlikely to happen but managed anyway') 

> gsub('(?:\\b|)([.,:;!]+)(?: |\\b)',' \\1 ',text) 
[1] "Hi ! stack-overflow ... is a popular website , I visit it every day . " 
[2] "aaa ... "                
[3] "AAA ... B\"B\"B"              
[4] "AA . BBB #unlikely to happen but managed anyway"  
+0

Зачем использовать '(?: \ B |)?'? Каковы ваши намерения здесь? –

+0

Чтобы быть уверенным, что мы находимся между границами слов или пробелами, например, посторонним тестом, чтобы избежать окружения пунктуацией пробелов в смайликах, например. – Tensibai

+1

Но [это не мешает этому] (https://regex101.com/r/tM0lR6/2). Группы не являются обязательными. Если вы сделаете их обязательными, это будет работать [как это] (https://regex101.com/r/tM0lR6/3). –