Regex para remover zeros à esquerda em R, a menos que o caractere final (ou único) seja zero

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" ""   ""

A expressão regular acima é desse encadeamento SO, explicando como remover todos os zeros à esquerda de uma sequência em R. Como conseqüência dessa expressão regular, "000" e "0" são transformados em "". Em vez disso, quero remover todos os zeros à esquerda de uma sequência de caracteres, exceto nos casos em que o caractere final é zero ou o único caractere é zero.

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

Esse outro thread do SO explica como fazer o que eu quero, mas acho que não estou obtendo a sintaxe correta, aplicando a solução em R. E realmente não entendo a distinção entre a 1ª e a 2ª solução abaixo ( se eles realmente funcionaram).

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"

Qual é a regex adequada em R para obter o que eu quero?

Jason Hunter
fonte

Respostas:

6

Você pode remover todos os zeros do início de uma string, mas não o último:

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

Veja a demonstração regex .

Detalhes

  • ^ - início de uma string
  • 0+ - um ou mais zeros
  • (?!$) - um indicador negativo que falha na correspondência se houver um fim da posição da corda imediatamente à direita da localização atual

Veja a demonstração R :

x <- c("005", "0AB", "000", "0")
sub("^0+(?!$)", "", x, perl=TRUE)
## => [1] "5"  "AB" "0"  "0"
Wiktor Stribiżew
fonte
11
regexnovato. Qual é a diferença de desempenho (ou outras preferências) entre seu padrão e este ^0*(.+)$ou ^0+(.+)$?
M--
2
@ M - Esses são padrões diferentes, é recomendável comparar apenas o desempenho de regexps equivalentes. Os seus são um pouco ineficientes, pois .podem corresponder 0e os dois padrões adjacentes são quantificados indefinidamente, mas apenas um pouquinho.
Wiktor Stribiżew
4

Podemos adicionar mais uma condição com uma pesquisa de expressão regular para verificar se há valores diferentes de zero após um ou mais zeros ( 0+)

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

dados

v1 <- c("005", "0AB", "000", "0")
akrun
fonte
11
Eu não sou um regexguru, mas as visões não são eficientes, são? Como você tem dois, subvocê pode remover todos os zeros à esquerda e substituí-los ""por 0? sub("^$", "0", sub("^0+", "", v1), perl = TRUE)
M--
2
@ M-- Não seria tão eficiente, mas eu usei-o para seguir o mesmo código que o OP
akrun
3

Você pode usar uma alternância para corresponder a todos os zeros na sequência em um grupo de captura ou corresponder a todos os zeros desde o início da sequência.

No grupo de substituição, use 1.

^0*(0)$|^0+

Regex demo | R demo

Por exemplo

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

Resultado

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

Ou melhor ainda, como comentado pelo Wiktor Stribiżew , você pode usar capturar um único 0 em um grupo e repetir o próprio grupo para capturar a última instância de um zero.

^(0)+$|^0+

Regex demo

O quarto pássaro
fonte
3
Eu usaria^(0)+$|^0+
Wiktor Stribiżew
3
Parece que sub("^0+(?!$)", "", x, perl=TRUE)também vai funcionar
Wiktor Stribiżew
2

Outro regex opção:

^0*(.+)$

Aqui está um demonstração do regex .

Usando base::sub em R:

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

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

Aqui está um R demonstração .

Ou expandindo a resposta de @ akrun :

sub("^$", "0", sub("^0+", "", c("005", "0AB", "000", "0")), perl = TRUE)
M--
fonte