Как заменить только один символ в регулярном выражении с помощью str_replace

#r #regex #stringr

#r #регулярное выражение #stringr

Вопрос:

Я пытаюсь стандартизировать некоторые нечетные строковые данные, используя регулярные выражения и str_replace_all . В некоторых случаях я хочу использовать наборы символов (например, [abc] ) или «подстановочные знаки» (например, d ), чтобы найти символ для замены, но я не хочу заменять эти наборы символов или подстановочные знаки.

Ниже data приведен тип данных, которые у меня есть, и clean это то, что я пытаюсь получить:

 data <- c("1ac 2b", "1 a", "1a b", "1a2b", "0")
clean <- c("1ac 2b", "1a", "1ab", "1a 2b", "0")
  

Я пытался создавать команды, такие как следующие:

 attempt1 <- str_replace_all(data, "[abc]\d", "[abc] \d")
attempt2 <- str_replace_all(data, " [abc]", "[abc])
  

В обеих этих попытках я в конечном итоге теряю нужные мне данные.

Кажется, что второй аргумент str_replace_all принимает регулярные выражения, но третий аргумент вычисляется буквально, поэтому в итоге я заменяю символы, которые не хочу заменять.

Есть ли какой-либо способ перенести значение подстановочного знака и наборов символов из части регулярного выражения команды в компонент replace? В качестве альтернативы, есть ли совершенно другой метод решения этой проблемы, который кто-нибудь порекомендовал бы?

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

Ответ №1:

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

Ваши replace и регулярные выражения должны быть:

 data <- c("1ac 2b", "1 a", "1a b", "1a2b", "0")

attempt1 <- str_replace_all(data, "([abc])(\d)", "\1 \2")
attempt2 <- str_replace_all(attempt1, " ([abc])", "\1")

> attempt2
[1] "1ac 2b" "1a"     "1ab"    "1a 2b"  "0" 
  

Вторая замена принимает attempt1 в качестве входных данных, чтобы применить оба правила замены. Вы могли бы записать оба выражения в одной строке, если хотите.

 str_replace_all(str_replace_all(data, "([abc])(\d)", "\1 \2"), " ([abc])", "\1")
  

Ответ №2:

Или в базовом использовании R gsub . Стратегия: Удалите все пробелы, затем добавьте пробелы перед цифрами, которые не являются границами слов. Это должно быть более общим.

 gsub("(\B\d)", " \1", gsub("\s", "", x))
# [1] "1ac 2b" "1a"     "1ab"    "1a 2b"  "0" 
  

Или обернутый в функцию.

 mySub <- function (x) {
  x <- gsub("\s", "", x)
  gsub("(\B\d)", " \1", x)
}
mySub(x)
# [1] "1ac 2b" "1a"     "1ab"    "1a 2b"  "0" 
  

Данные

 x <- c("1ac 2b", "1 a", "1a b", "1a2b", "0")
  

Комментарии:

1. Вы бы порекомендовали использовать gsub вместо функций stringr?

2. Ну, вы знаете, это зависит от того, что вы собираетесь делать с R. Если вы используете его только время от времени, возможно, усилия не стоят того, чтобы изучать его должным образом. Тогда, вероятно, достаточно использовать новый пакет для каждой задачи. R, однако, является обширным языком программирования с непрерывной логикой. Довольно часто логика дополнительных пакетов значительно отличается от R-логики, что может быть довольно запутанным. Вот почему я по возможности обходлюсь без дополнительных пакетов.

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