Как добавить удаленное место в предложении? - PullRequest
3 голосов
/ 10 мая 2019

У меня есть следующая строка:

x = "marchTextIWantToDisplayWithSpacesmarch"

Я хотел бы удалить часть 'march' в начале строки, а затем добавить пробел перед каждой заглавной буквой в остатке, чтобы получить следующий результат:

"Text I Want To Display With Spacesmarch"

Чтобы вставить пробел, я использовал gsub("([a-z]?)([A-Z])", "\\1 \\2", x, perl= T), но я понятия не имею, как изменить шаблон так, чтобы первый «марш» был исключен из возвращаемой строки. Я пытаюсь стать лучше в этом, поэтому любая помощь будет принята с благодарностью.

Ответы [ 4 ]

5 голосов
/ 10 мая 2019

Можно было бы захватить заглавную букву в виде группы ((...)) и в замене создать пробел, за которым следует обратная ссылка (\\1) захваченной группы

gsub("([A-Z])", " \\1", x)
#[1] "march Text I Want To Display With Spacesmarch"

Если нам нужно удалить «марш»

sub("\\b[a-z]\\w+\\s+", "", gsub("([A-Z])", " \\1", x))
[#1] "Text I Want To Display With Spacesmarch"

данные

x <- "marchTextIWantToDisplayWithSpacesmarch"
4 голосов
/ 10 мая 2019

Нет, вы не можете добиться замены, используя одну gsub, потому что в одном из ваших требований вы хотите удалить все строчные буквы, начиная с начала, а ваше второе требование - вводить пробел перед каждой заглавной буквой, кроме первая заглавная буква результирующей строки после удаления всех строчных букв из начала текста.

Выполнение этого в одном вызове gsub было бы возможно в тех случаях, когда каким-либо образом мы можем повторно использовать некоторые из существующих символов для условной замены, чего здесь не может быть. Таким образом, на первом шаге вы можете использовать ^[a-z]+ регулярное выражение, чтобы избавиться от всех строчных букв только с начала строки,

sub('^[a-z]+', '', "marchTextIWantToDisplayWithSpacesmarch")

оставив вас с этим,

[1] "TextIWantToDisplayWithSpacesmarch"

И на следующем шаге вы можете использовать это (?<!^)(?=[A-Z]) регулярное выражение, чтобы вставить пробел перед каждой заглавной буквой, кроме первой, поскольку вам может не потребоваться дополнительный пробел перед предложением. Но вы можете объединить оба и записать их так:

gsub('(?<!^)(?=[A-Z])', ' ', sub('^[a-z]+', '', "marchTextIWantToDisplayWithSpacesmarch"), perl=TRUE)

, который даст вам желаемую строку,

[1] "Text I Want To Display With Spacesmarch"

Edit: Объяснение (?<!^)(?=[A-Z]) шаблон

Во-первых, давайте просто возьмем (?=[A-Z]) шаблон

См. Розовые маркеры в этой демонстрации

Как вы можете видеть, в демо каждой заглавной букве предшествует розовая метка, которая является местом, где будет вставлен пробел. Но мы не хотим вставлять пробел перед самой первой буквой, так как это не нужно. Следовательно, нам нужно условие в регулярном выражении, которое не выберет первую заглавную букву, которая появляется в начале строки. И для этого нам нужно использовать отрицательный взгляд за (?<!^), что означает, что Не выбирайте позицию, которой предшествует начало строки , и, следовательно, это (?<!^) помогает отбрасывать заглавную букву, которая предшествует только начало строки.

См. Эту демонстрацию, где розовый маркер исчез из самой первой заглавной буквы

Надеюсь, это проясняет, как выбирается любая другая заглавная буква, но не самая первая. Дайте мне знать, если у вас есть какие-либо вопросы.

3 голосов
/ 10 мая 2019

Вы можете использовать один вызов регулярного выражения для gsub в сочетании с trimws, чтобы обрезать результирующую строку:

trimws(gsub("^\\p{Ll}+|(?<=.)(?=\\p{Lu})", " ", x, perl=TRUE))
## => [1] "Text I Want To Display With Spacesmarch"

Он также поддерживает все строчные буквы Юникода (\p{Ll}) и прописные буквы (* 1007)*) букв.

См. демонстрационную версию R онлайн и демонстрационную версию regex .

Подробности

  • ^\\p{Ll}+ - 1 или более строчных букв в начале строки
  • | - или
  • (?<=.)(?=\\p{Lu}) - любое место между любым символом, кроме символов перевода строки и заглавной буквы.

Вот альтернативный вариант с одним вызовом gsubfn регулярных выражений с некоторой логикой ifelse:

> gsubfn("^\\p{Ll}*(\\p{L})|(?<=.)(?=\\p{Lu})", function(n) ifelse(nchar(n)>0,n," "), x, perl=TRUE,backref=-1) 
[1] "Text I Want To Display With Spacesmarch"

Здесь часть ^\\p{Ll}*(\\p{L}) соответствует 0+ нижнему региструбуквы и вводит следующую заглавную букву в группу 1, к которой можно получить доступ, передав аргумент n анонимной функции.Если длина n не равна нулю, эта альтернатива совпадает, и нам нужно заменить это значение.Иначе мы заменим пробел.

1 голос
/ 10 мая 2019

Так как это помечено perl, мои 2 цента:

Можете ли вы объединить замены внутри sub() и gsub()? В более новых версиях perl к подстановке s/// может быть добавлена ​​опция /r, чтобы сопоставленная строка могла быть возвращена «неразрушающим» образом, а затем снова сопоставлена. Это позволяет выполнять хакерское сопоставление / замену / повторные совпадения без использования расширенного синтаксиса, например, :

perl -E '
  say "marchTextIWantToDisplayWithSpacesmarch" =~
  s/\Amarch//r =~ s/([[:upper:]])/ $1/gr  =~ s/\A\s//r;'

выход

Text I Want To Display With Spacesmarch

Похоже, это то, что @ pushpesh-kumar-rajwanshi и @akrun делают, заключая gsub в sub() (и наоборот). В общем, я не думаю, что perl = T отражает полное великолепно развитое безумие регулярных выражений Perl ; -) , но gsub/sub должно быстро работать с векторами, нет?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...