shellscript characters bash strip

bash - characters - Eliminar ceros iniciales antes de pasar una variable de shell a otro comando



trim shellscript (13)

Resulta que iptables no maneja los ceros iniciales demasiado bien. Como $machinenumber que se usa debe tener un cero $nozero para otros propósitos, la idea es simplemente crear una nueva variable ( $nozero ) basada en $machinenumber , donde se eliminan los ceros $nozero .

$machinenumber es un número de dos dígitos entre 01 y 24. Actualmente es 09

$machinetype es de 74 por ahora y no ha causado ningún problema antes.

Lo que tengo hasta ahora es:

nozero = (echo $machinenumber | sed ''s/^0*//'') iptables -t nat -I POSTROUTING -s 10.($machinetype).($nozero).0/24 -j MASQUERADE

Aunque creo que estoy en el camino correcto, el código da como resultado:

ERROR - Unknown string operation


En bash es lo más simple:

%> a=00123 %> b=${a//0/}

El valor de b es ahora "123". La forma general es ${varname//find/replace} y reemplaza cualquier número de apariciones de find .


Lo hago usando

awk ''{print $1 + 0}''

Me gusta esto mejor que el enfoque sed porque aún funciona con números como 0, 000 y 001.

Así que en tu ejemplo yo reemplazaría

nozero=$(echo $machinenumber | sed ''s/^0*//'')

con

nozero=$(echo $machinenumber | awk ''{print $1 + 0}'' )


No necesitas usar sed u otra utilidad externa. Aquí hay un par de maneras en que Bash puede quitarte los ceros iniciales.

iptables -t nat -I POSTROUTING -s "10.$machinetype.$((10#$machinenumber)).0/24" -j MASQUERADE

El $(()) configura un contexto aritmético y el 10# convierte el número de la base 10 a la base 10 causando que se caigan los ceros iniciales.

shopt -s extglob iptables -t nat -I POSTROUTING -s "10.$machinetype.${machinenumber##+(0)}.0/24" -j MASQUERADE

Cuando extglob está activado, la expansión de parámetros que se muestra elimina todos los ceros iniciales. Desafortunadamente, si el valor original es 0, el resultado es una cadena nula.


No puedo comentar ya que no tengo suficiente reputación, pero sugeriría que aceptes la respuesta de Dennis (que es realmente muy buena)

En primer lugar, no creo que tu respuesta sea válida. En mi instalación me sale:

> machinetype=74 > machinenumber=05 > iptables -t nat -I POSTROUTING -s 10.($machinetype).($machinenumber + 0).0/24 -j MASQUERADE -bash: syntax error near unexpected token `('' > echo 10.($machinetype).($machinenumber + 0).0/24 -bash: syntax error near unexpected token `(''

Si lo cito me sale:

> echo "($machinetype).($machinenumber + 0)" (74).(05 + 0)

Supongo que te refieres a:

> echo 10.$(($machinetype)).$(($machinenumber + 0)).0/24 10.74.5.0/24

Pero, por supuesto, sigue siendo una mala solución debido a octal:

> machinenumber=09 > echo 10.$(($machinetype)).$(($machinenumber + 0)).0/24 -bash: 09: value too great for base (error token is "09")

Supongo que sus números no son 08 o 09 en este momento.

Aquí está la de Dennis:

> echo $((10#09)) 9 > echo $((10#00)) 0 > echo $((10#00005)) 5 > echo $((10#)) 0

Es cierto que este último podría ser un problema de validación de entrada para alguien.

La solución sed tiene el problema de:

> echo "0" | sed ''s/^0*//'' >


No, tú haces todo (casi todo) correcto. Solo debes:

  • eliminar espacios alrededor de =
  • use $() o backticks en lugar de ()

Eso sería correcto:

nozero=$(echo $machinenumber | sed ''s/^0*//'')

También debes usar variables sin () alrededor. Puedes agregar "" si quieres:

iptables -t nat -I POSTROUTING -s "10.$machinetype.$nozero.0/24" -j MASQUERADE

Y por supuesto las variables aquí no son necesarias. Puedes decir simplemente:

iptables -t nat -I POSTROUTING -s "10.$(echo $machinenumber | sed ''s/^0*//'').$nozero.0/24" -j MASQUERADE


Si estás usando bash, esto parece el más simple:

nozero=$(bc<<<$machinenumber)


Tampoco puedo comentar o votar aún, pero la respuesta de Duncan Irvine es la mejor.

Me gustaría añadir una nota sobre la portabilidad. La sintaxis de $((10#0009)) no es portátil. Funciona en bash y ksh, pero no en dash:

$ echo $((10#09)) dash: 1: arithmetic expression: expecting EOF: "10#09" $ dpkg -s dash | grep -i version Version: 0.5.7-2ubuntu2

Si la portabilidad es importante para usted, use la respuesta sed.


Tuve que volver a visitar este código el otro día debido a algunas cosas no relacionadas, y debido a la compatibilidad con algún otro software que lee el mismo script, encontré que es mucho más fácil volver a escribirlo en este, que todavía debería ser válido bash:

iptables -t nat -I POSTROUTING -s 10.($machinetype).($machinenumber + 0).0/24 -j MASQUERADE

Básicamente, agregar 0 obliga a que se interprete como un entero, por lo tanto, eliminando automáticamente los ceros iniciales


Una solución de bash puro:

> N=0001023450 > [[ $N =~ "0*(.*)" ]] && N=${BASH_REMATCH[1]} > echo $N 1023450


Utilizando sed:

echo 000498 | sed "s/^0*/([1-9]/)//1/;s/^0*$/0/" 498 echo 000 | sed "s/^0*/([1-9]/)//1/;s/^0*$/0/" 0


Yo diría que estás muy cerca. No veo un requisito establecido para bash, pero su lógica distinta de cero es errónea.

nonzero=`echo $machinenumber + 0 | bc` iptables -t nat -I POSTROUTING -s 10.$machinetype.$nozero.0/24 -j MASQUERADE

Agregar 0 es un método común para cambiar un número de cadena a un entero sin relleno. bc es una calculadora básica. Uso este método para eliminar el espacio y el relleno cero de los números todo el tiempo.

Si bien no soy experto en la sintaxis de iptables, estoy bastante seguro de que los paréntesis no son necesarios. Como ya tengo caracteres que no son de palabras que rodean ambas variables, no necesito recintos especiales a su alrededor. Los caracteres de las palabras son;

[a-zA-z0-9_]

Al utilizar esta solución, no pierde el cero como valor potencial y debe ser transportable en todos los shells.


también puedes hacer

machinenumber=$(expr $machinenumber + 0)


nozero=$(echo $machinenumber | sed ''s/^0*//'')

Prueba sin los espacios alrededor de = y con un signo $ adicional.