2012-06-20 20 views
28

Resulta que iptables no maneja demasiado bien los ceros a la izquierda. Como el $machinenumber que se utiliza debe tener un cero inicial para otros fines, la idea es simplemente crear una nueva variable ($nozero) basada en $machinenumber, donde se eliminan los ceros iniciales.Eliminación de ceros a la izquierda antes de pasar una variable de shell a otro comando

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

$machinetype es 74 y por ahora no ha causado problemas 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, los resultados de código en:

ERROR - Unknown string operation 

Respuesta

0

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

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

Básicamente, la adición de 0 fuerzas que sea interpretado como un entero, por lo tanto, pelar automáticamente los ceros iniciales

+1

¿Eh? '($ machinenumber + 0)' no es sintaxis matemática en bash. –

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

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

18

No, usted hace todo (alomost todo) correcto. Sólo debe:

  • espacios quitan alrededor =
  • uso $() o acentos abiertos en lugar de ()

que sería correcta:

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

También debe utilizar variables sin () alrededor de ellos. Puede añadir "" si quieres:

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

Y de variables curso aquí no son necesarios. Se puede decir simplemente:

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

Funciona, salud. ¿Qué pasa si quiero cocerlo en el comando de iptables, pero? Prefiero no declarar ninguna variable nueva. – Jarmund

+0

@Jarmund: funcionará también. Sería incluso mejor. –

+0

¿Podría proporcionarme la sintaxis correcta? Mis scripts de bash son dudosos en el mejor de los casos. – Jarmund

13

también se puede hacer

machinenumber=$(expr $machinenumber + 0) 
+0

Este resultó ser el enfoque más simple y funcional: 'iptables -t nat -I POSTROUTING -s 10. ($ Machinetype). ($ Machinenumber + 0) .0/24 - j MASQUERADE' – Jarmund

40

No es necesario utilizar sed u otra utilidad externa. Aquí hay un par de formas en que Bash puede quitar los ceros iniciales para ti.

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

Los $(()) establece un contexto aritmética y la 10# convierte el número de base 10 a la base 10 haciendo que los ceros a ser dejados.

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

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

+9

El '10 #' es la solución más simple y elegante que he encontrado hasta ahora. ¡Gracias! – desgua

+0

'echo $ ((10 # $ {machinenumber}))' funciona en kornshell también! Estaba buscando un no bashismo y esto debería funcionar bien. ksh M-11/16/88f – bgStack15

+0

Funciona en zsh, también. –

2

I hacerlo a través de

awk '{print $1 + 0}' 

me gusta esta mejor que el enfoque de sed, ya que todavía funciona con números como 0, 000, y 001.

Así que en tu ejemplo me gustaría sustituir

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

con

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

8

No puedo hacer ningún comentario ya que no tengo suficiente reputación, pero le sugiero que acepte Dennis's answer (que es realmente bastante limpio)

En primer lugar, no creo que tu respuesta sea válida bash. En mi install 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) 

Te estoy asumiendo decir:

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

Pero, por supuesto, sigue siendo un mal solución por 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í es Dennis de:

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

cierto que esta última podría ser un problema de validación de entradas para alguien.

La solución SED tiene el problema de:

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

> 
4

Una solución pura fiesta:

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

Sería '[[" $ N "= ~^0 * (. +) $]] && N =" $ {BASH_REMATCH [1]} '' - eso también funciona para N = "000" y N = " 0 ". Considere también '[[" $ N "= ~^0 * ([0-9] +) $]]' – Zrin

2

Tampoco puedo comentar o votar todavía, pero la respuesta Duncan Irvine es el mejor .

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

$ 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, utilice la respuesta sed.

3

usando 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 
-3

En bash es más simple:

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

El valor de b es ahora "123". El formulario general es ${varname//find/replace} y reemplaza cualquier cantidad de ocurrencias de find.

+0

¿No eliminaría ese regex también otros ceros? ES DECIR. 0102030 => 123 – Jarmund

+0

Tiene toda la razón. Elimina todas las apariciones. Entonces, todo lo que escribí no estaba mal, aunque no resolvía el problema original. :-) – gsl

1

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

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

La adición de 0 es un método común para cambiar un número de serie en un entero no relleno. bc es una calculadora básica. Utilizo este método para eliminar espacio y cero relleno de 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 sin palabras que bordean ambas variables, no necesito cierres especiales a su alrededor. Los personajes de Word son;

[a-zA-z0-9_] 

Con esta solución, no pierde cero como valor potencial, y debe ser portátil en todos los proyectiles.

Cuestiones relacionadas