заменить число, превышающее 5 цифр в тексте

#r #regex #gsub #regex-group #data-masking

#r #регулярное выражение #gsub #группа регулярных выражений #маскировка данных

Вопрос:

 a <- c("this is a number 9999333333 and i got 12344")
  

Как я мог бы заменить число, превышающее 5 цифр, дополнительными цифрами, равными «X»

Ожидаемый результат:

 "this is a number 99993XXXXX and i got 12344"
  

Код, который я пробовал:

 gsub("(.{5}).*", "X", a)
  

Ответ №1:

Вы можете использовать gsub с регулярным выражением PCRE:

 (?:G(?!^)|(?<!d)d{5})Kd
  

Смотрите демонстрацию регулярных выражений. Подробные сведения:

  • (?:G(?!^)|(?<!d)d{5}) — конец предыдущего успешного совпадения ( G(?!^) ) или ( | ) местоположение, которому не предшествует цифра ( (?<!d) ), а затем любые пять цифр
  • K — оператор сброса соответствия, отбрасывающий весь текст, который был сопоставлен до сих пор
  • d — цифра.

Смотрите демонстрацию R:

 a <- c("this is a number 9999333333 and i got 12344")
gsub("(?:\G(?!^)|(?<!\d)\d{5})\K\d", "X", a, perl=TRUE)
## => [1] "this is a number 99993XXXXX and i got 12344"
  

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

1. Спасибо, если я хочу заменить X после первых 2 цифр на числа, превышающие 5 цифр, как я могу это изменить, например: «это число 99XXXXXXXX, и я получил 12344»

2. @prog Затем используйте gsub("(?:\G(?!^)|(?<!\d)\d{2}(?=\d{4}))\K\d", "X", a, perl=TRUE) . (?=d{4}) Положительный прогноз требует, чтобы еще четыре цифры появлялись сразу после первых двух.

Ответ №2:

gsubfn в пакете gsubfn это похоже на gsub за исключением того, что строка замены может быть функцией, которая вводит группы захвата и выводит замену на соответствие. Функция может быть необязательно выражена в виде формулы, как мы делаем здесь.

Регулярное выражение (d{5}) сопоставляет и фиксирует 5 цифр и (d ) сопоставляет и фиксирует оставшиеся цифры. Две группы захвата загружаются в функцию и вставляются обратно вместе, за исключением того, что каждый символ во второй заменяется на X . r"{...}" это обозначение для строковых литералов, введенное в R 4.0, которое устраняет необходимость использования двойной обратной косой черты для обозначения обратной косой черты в строковом литерале.

 library(gsubfn)

gsubfn(r"{(d{5})(d )}", ~ paste0(x, gsub(".", "X", y)), a)
## [1] "this is a number 99993XXXXX and i got 12344"
  

Если мы заменим первый аргумент регулярным выражением r"{(d{2})(d{4,})}" , то оно заменит все цифры, кроме первых двух, при условии, что их не менее 6 цифр.

Ответ №3:

Альтернативный способ, не использующийся gsub для замены чисел, превышающих 5 цифр в тексте, состоит в том, чтобы разделить строку на strsplit , проверить, есть ли только цифры, и объединить substr и a strrep :

 paste(lapply(strsplit(a, " ")[[1]], function(x) {
  if(!grepl("\D", x)) {
    paste0(substr(x, 1, 5), strrep("X", pmax(0, nchar(x)-5)))
  } else {x}}), collapse = " ")
#[1] "this is a number 99993XXXXX and i got 12344"
  

Заменить X после первых 2 цифр для чисел, превышающих 5 цифр:

 paste(lapply(strsplit(a, " ")[[1]], function(x) {
  if(!grepl("\D", x) amp; nchar(x) > 5) {
    paste0(substr(x, 1, 2), strrep("X", pmax(0, nchar(x)-2)))
  } else {x}}), collapse = " ")
#[1] "this is a number 99XXXXXXXX and i got 12344"