Regex para eliminar los ceros iniciales en R, a menos que el carácter final (o único) sea cero

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

La expresión regular anterior es de este hilo SO que explica cómo eliminar todos los ceros a la izquierda de una cadena en R. Como consecuencia de esta expresión regular, tanto "000" como "0" se transforman en "". En cambio, quiero eliminar todos los ceros a la izquierda de una cadena de caracteres, excepto en los casos en que el carácter final sea cero o el único carácter sea cero.

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

Este otro hilo SO explica cómo hacer lo que quiero, pero no creo que esté obteniendo la sintaxis bastante correcta, aplicando la solución en R. Y realmente no entiendo la distinción entre la primera y la segunda solución a continuación ( si de verdad funcionaran).

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"

¿Cuál es la expresión regular adecuada en R para obtener lo que quiero?

Jason Hunter
fuente

Respuestas:

6

Puede eliminar todos los ceros desde el inicio de una cadena, pero no el último:

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

Ver la demostración de expresiones regulares .

Detalles

  • ^ - inicio de una cadena
  • 0+ - uno o más ceros
  • (?!$) - una anticipación negativa que falla la coincidencia si hay una posición de final de cadena inmediatamente a la derecha de la ubicación actual

Ver la demostración de R :

x <- c("005", "0AB", "000", "0")
sub("^0+(?!$)", "", x, perl=TRUE)
## => [1] "5"  "AB" "0"  "0"
Wiktor Stribiżew
fuente
1
regexnovato. ¿Cuál es la diferencia de rendimiento (u otras preferencias) entre su patrón y este ^0*(.+)$o ^0+(.+)$?
M--
2
@ M-- Estos son patrones diferentes, se recomienda comparar solo el rendimiento de expresiones regulares equivalentes. Los suyos son un poco ineficientes ya que .pueden coincidir 0y ambos patrones adyacentes se cuantifican indefinidamente, pero solo un poco.
Wiktor Stribiżew
4

Podemos agregar una condición más con una búsqueda de expresiones regulares para verificar cualquier valor distinto de cero después de uno o más ceros ( 0+)

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

datos

v1 <- c("005", "0AB", "000", "0")
akrun
fuente
1
No soy regexgurú de ninguna manera, pero las búsquedas no son eficientes, ¿verdad? Dado que tiene dos, subes posible que desee eliminar todos los ceros iniciales y reemplazarlos ""con 0? sub("^$", "0", sub("^0+", "", v1), perl = TRUE)
M--
2
@ M-- No sería tan eficiente, pero lo usé para seguir el mismo código que el OP
akrun el
3

Puede usar una alternancia para hacer coincidir todos los ceros en la cadena en un grupo de captura o hacer coincidir todos los ceros desde el comienzo de la cadena.

En el reemplazo use el grupo 1.

^0*(0)$|^0+

Regex demo | Demo R

Por ejemplo

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

Salida

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

O incluso mejor, como comentó Wiktor Stribiżew , podría usar capturar un solo 0 en un grupo y repetir el grupo en sí para capturar la última instancia de un cero.

^(0)+$|^0+

Demo de expresiones regulares

El cuarto pájaro
fuente
3
Yo usaría^(0)+$|^0+
Wiktor Stribiżew
3
Parece sub("^0+(?!$)", "", x, perl=TRUE)que también funcionará
Wiktor Stribiżew
2

Otra regexopcion:

^0*(.+)$

Aquí hay una demostración de expresiones regulares .

Usando base::suben R:

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

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

He aquí una demostración R .

O expandiendo la respuesta de @akrun :

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