2012-06-20 7 views
28

Okazuje się, że iptables nie radzi sobie z wiodącymi zerami zbyt dobrze. Ponieważ użyte w tym celu $machinenumber musi mieć wiodące zero w innych celach, chodzi po prostu o utworzenie nowej zmiennej ($nozero) opartej na $machinenumber, gdzie zerowanie zer wiodących.Usuwanie początkowych zer przed przekazaniem zmiennej powłoki do innego polecenia

$machinenumber to dwucyfrowa liczba między 01 i 24. Obecnie jest to 09

$machinetype wynosi 74 do teraz i nie spowodowała żadnych problemów wcześniej.

Co mam tak daleko jest:

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

Chociaż uważam, że jestem na dobrej drodze, wyniki kodowe w:

ERROR - Unknown string operation 

Odpowiedz

0

Musiałem ponownie obejrzeć ten kod na drugi dzień z powodu pewnych niezwiązanych ze sobą rzeczy, a ze względu na kompatybilność z innym oprogramowaniem, które czyta ten sam skrypt, znalazłem go najłatwiejszy do przepisania go na ten, który powinien być nadal ważny bash:

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

Zasadniczo, dodając sił 0 to być interpretowane jako liczba całkowita, a więc automatycznie odpędzenie zer

+1

Huh? '($ machinenumber + 0)' nie jest składnią matematyczną w bashu. –

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

Try bez spacji przy = oraz z dodatkowym znakiem $.

18

Nie, wszystkie (wszystkie) są poprawne. Po prostu musi:

  • obowiązuje usuń wokół =
  • użycie $() lub backticks zamiast ()

To byłoby poprawne:

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

Również należy użyć zmiennych bez () dookoła nich. Możesz dodać "" jeśli chcesz:

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

A zmiennych oczywiście tutaj nie są konieczne. Można powiedzieć po prostu:

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

Działa, okrzyki. Co jeśli chciałbym upiec to w poleceniu iptables, prawda? Wolę nie zadeklarować żadnych nowych zmiennych. – Jarmund

+0

@Jarmund: będzie działać również. Byłoby nawet lepiej muche –

+0

Czy mógłbyś podać mi poprawną składnię? Skrypty mojego basha są w najlepszym wypadku niestosowne. – Jarmund

13

można też zrobić

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

To okazało się najprostsze, działające podejście: 'iptables -t nat -I POSTROUTING -s 10. ($ Machinetype). ($ Machinenumber + 0) .0/24 - j MASQUERADE' – Jarmund

40

Nie trzeba używać sed lub innego narzędzia zewnętrznego. Oto kilka sposobów, w jakie Bash może usunąć początkowe zera.

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

W $(()) ustanawia arytmetyczna kontekstu i 10# przekształca liczbę od podstawy 10 do podstawy 10 powodując żadnych zer wiodących być pominięte.

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

extglob gdy jest włączone, rozszerzenie parametrów przedstawionych usuwa wszystkie zera. Niestety, jeśli oryginalna wartość wynosi 0, wynikiem jest łańcuch pusty.

+9

'10 # 'jest najprostszym i najbardziej eleganckim rozwiązaniem, jakie do tej pory znalazłem. Dziękuję Ci! – desgua

+0

'echo $ ((10 # $ {machinenumber}))' działa również w kornshell! Szukałem non-bashism i to powinno działać dobrze. ksh M-11/16/88f – bgStack15

+0

Działa również w zsh. –

2

mogę to zrobić za pomocą

awk '{print $1 + 0}' 

Lubię to lepiej niż sed podejściem jak to działa z liczbami jak 0, 000, i 001.

Więc w przykładzie chciałbym wymienić

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

z

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

8

Nie mogę komentować, ponieważ nie mam wystarczającej reputacji, ale proponuję zaakceptować Dennis's answer (który jest naprawdę całkiem zgrabny)

Po pierwsze, nie sądzę, że twoja odpowiedź jest poprawna bash. W mojej instalacji otrzymuję:

> 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 `(' 

Jeśli cytuję go uzyskać:

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

Jestem przy założeniu chodziło Ci o:

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

Ale oczywiście to wciąż zły rozwiązanie z powodu ósemkowego:

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

Zakładam, że twoje numery nie są w tej chwili 08 lub 09.

Oto Dennisa:

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

Trzeba przyznać, że ostatni z nich może być problemem dla kogoś, sprawdzania poprawności danych wejściowych.

SED rozwiązanie ma problemu:

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

> 
4

Czysty rozwiązanie bash:

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

Będzie to "[[" $ N "= ~^0 * (. +) $]] && N =" $ {BASH_REMATCH [1]} "' - to również działa dla N = "000" i N = " 0 ". Rozważ również: [["$ N" = ~^0 * ([0-9] +) $]] ' – Zrin

2

ja również nie może wypowiedzieć ani głosować w górę jeszcze, ale odpowiedź Duncan Irvine jest najlepszy .

Chciałbym dodać notatkę o przenośności. Składnia $((10#0009)) nie jest przenośna. Działa w bash i ksh, ale nie w desce rozdzielczej:

$ echo $((10#09)) 
dash: 1: arithmetic expression: expecting EOF: "10#09" 

$ dpkg -s dash | grep -i version 
Version: 0.5.7-2ubuntu2 

Jeśli przenośność jest dla Ciebie ważna, skorzystaj z odpowiedzi sed.

3

Stosując 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

W bashu jest najprostsze:

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

Wartość B jest "123". Ogólna forma to ${varname//find/replace} i zastępuje dowolną liczbę wystąpień find.

+0

Czy to nie oznacza, że ​​regex usuwa również inne zera? TO ZNACZY. 0102030 => 123 – Jarmund

+0

Masz całkowitą rację. Usuwa wszystkie wystąpienia. Więc wszystko, co napisałem, nie było złe, chociaż nie rozwiązałem pierwotnego problemu. :-) – gsl

1

Powiedziałbym, że jesteś bardzo blisko. Nie widzę wymogu określonego dla bash, ale twoja niezerowa logika jest wadliwa.

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

Dodawanie 0 jest popularną metodą zmiany numeru ciągu na niewypełnioną liczbę całkowitą. bc to podstawowy kalkulator. Używam tej metody do usuwania spacji i zerowego wypełniania liczb przez cały czas.

Chociaż nie jestem ekspertem w składni iptables, jestem prawie pewien, że nawiasy nie są konieczne. Ponieważ mam już znaki nie-słowne graniczące z obydwoma zmiennymi, nie potrzebuję specjalnych obudów wokół nich. Znaki słowne są;

[a-zA-z0-9_] 

korzystania z tego rozwiązania, aby nie stracić zera jako potencjalną wartość i powinny być przenośne na wszystkich muszli.

Powiązane problemy