Я предлагаю решение, подобное этому:
test <- c("i really wasn aware and i wasnt aware at all. but i wasn't aware. just wasn't. this wasn45'e meant to be. it wasn@'re simple", "Wasn&^$tt that nice?", "You say wasnmmmt?", "No, he wasn&#t#@$.", "She wasn%#@t##, I know.")
gsub("\\b(wasn)\\S*\\b(?:\\S*(\\p{P})\\B)?", "\\1't\\2", test, ignore.case=TRUE, perl=TRUE)
[1] "i really wasn't aware and i wasn't aware at all. but i wasn't aware. just wasn't. this wasn't meant to be. it wasn't simple"
[2] "Wasn't that nice?"
[3] "You say wasn't?"
[4] "No, he wasn't."
[5] "She wasn't, I know."
См. онлайн R демо .
Это решение учитывает случаи, когда wasn*
появляется в начале строки или пишется с большой буквы и не заменяет конечную пунктуацию.
Детали шаблона
\\b
- граница слова
(wasn)
- Группа захвата 1 (позднее обозначается \\1
в шаблоне замены): подстрока wasn
(без учета регистра из-за ignore.case=TRUE
)
\\S*\\b
- любые 0+ символов, кроме пробелов, за которыми следует граница слова
(?:\\S*(\\p{P})\\B)?
- необязательная группа без захвата, соответствующая 1 или 0 вхождениям
\\S*
- 0+ непробельных символов
(\\p{P})
- Группа захвата 2 (позднее обозначается \\2
в шаблоне замены): любая 1 пунктуация (не символ! \p{P}
не равна [:punct:]
!), За которой не следует символ .. .
\\B
- буква, цифра или _
(это шаблон, не состоящий из слов).
Для еще более сложных строк (например, She wasn%#@t##,$#^ I know.
), когда знаки препинания могут находиться внутри других символов пунктуации, вы можете ограничить пунктуацию, на которой вы хотите остановиться, используя пользовательское выражение в скобках и добавив \S*
в конце:
gsub("\\b(wasn)\\S*\\b(?:\\S*([?!.,:;])\\S*)?", "\\1't\\2", test, ignore.case=TRUE, perl=TRUE)
См. Демоверсию regex .