Regex для удаления начальных нулей в R, если только последний (или единственный) символ не равен нулю

9
gsub("(?<![0-9])0+", "", c("005", "0AB", "000", "0"), perl = TRUE)
#> [1] "5"  "AB" ""   ""
gsub("(^|[^0-9])0+", "\\1", c("005", "0AB", "000", "0"), perl = TRUE)
#> [1] "5"  "AB" ""   ""

Приведенное выше регулярное выражение взято из этого потока SO, объясняющего, как удалить все начальные нули из строки в R. В результате этого регулярного выражения и «000», и «0» преобразуются в «». Вместо этого я хочу удалить все начальные нули из строки символов, за исключением случаев, когда последний символ равен нулю или единственный символ равен нулю.

"005" would become "5"
"0AB" would become "AB"
"000" would become "0"
"0"   would become "0"

Этот другой поток SO объясняет, как делать то, что я хочу, но я не думаю, что я получаю синтаксис достаточно правильно, применяя решение в R. И я не очень понимаю различие между 1-м и 2-м решениями ниже ( если они действительно работали).

gsub("s/^0*(\d+)$/$1/;", "", c("005", "0AB", "000", "0"), perl = TRUE)  # 1st solution
# Error: '\d' is an unrecognized escape in character string starting ""s/^0*(\d"
gsub("s/0*(\d+)/$1/;", "", c("005", "0AB", "000", "0"), perl = TRUE)    # 2nd solution
# Error: '\d' is an unrecognized escape in character string starting ""s/0*(\d"

Что такое правильное регулярное выражение в R, чтобы получить то, что я хочу?

Джейсон Хантер
источник

Ответы:

6

Вы можете удалить все нули в начале строки, но не в последнем:

sub("^0+(?!$)", "", x, perl=TRUE)

Смотрите демо регулярных выражений .

подробности

  • ^ - начало строки
  • 0+ - один или несколько нулей
  • (?!$) - отрицательный прогноз, который не соответствует совпадению, если сразу после текущей позиции есть конец строки

Смотрите демоверсию R :

x <- c("005", "0AB", "000", "0")
sub("^0+(?!$)", "", x, perl=TRUE)
## => [1] "5"  "AB" "0"  "0"
Виктор Стрибьев
источник
1
regexновичек. Что разница в производительности (или другие предпочтения) между рисунком и этим ^0*(.+)$или ^0+(.+)$?
М--
2
@ M-- Это разные шаблоны, рекомендуется сравнивать только производительность эквивалентных регулярных выражений. Ваши немного неэффективны, так как .могут совпадать, 0и оба соседних шаблона неопределенно количественно, но совсем немного.
Wiktor Stribi Decew
4

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

sub("(?<![0-9])0+(?=[^0])", "", sub("^0+$", "0", v1), perl = TRUE)
#[1] "5"  "AB" "0"  "0" 

данные

v1 <- c("005", "0AB", "000", "0")
akrun
источник
1
Я не regexгуру в любом случае, но взгляды не эффективны, не так ли? Поскольку у вас есть два, subвы можете удалить все ведущие нули и заменить ""на 0? sub("^$", "0", sub("^0+", "", v1), perl = TRUE)
М--
2
@ M-- Это было бы не так эффективно, но я использовал его, чтобы следовать тому же коду, что и OP
akrun
3

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

В замене используйте группу 1.

^0*(0)$|^0+

Regex demo | R демо

Например

sub("^0*(0)$|^0+", "\\1", c("005", "0AB", "000", "0"))

Вывод

[1] "5"  "AB" "0"  "0"

Или даже лучше, как прокомментировал Wiktor Stribiżew , вы можете использовать захват одного 0 в группе и повторение самой группы, чтобы захватить последний экземпляр нуля.

^(0)+$|^0+

Regex demo

Четвертая птица
источник
3
Я бы использовал^(0)+$|^0+
Wiktor Stribiżew
3
Похоже sub("^0+(?!$)", "", x, perl=TRUE), также будет работать
Wiktor Stribiżew
2

Другой regexвариант:

^0*(.+)$

Вот демонстрация регулярных выражений .

Использование base::subв R:

sub("^0*(.+)$", "\\1", c("005", "0AB", "000", "0"))  

 ## [1] "5"  "AB" "0"  "0" 

Вот R демо .

Или расширив ответ @ akrun :

sub("^$", "0", sub("^0+", "", c("005", "0AB", "000", "0")), perl = TRUE)
M--
источник