2012-06-20 2 views
28

Оказывается, что iptables слишком плохо обрабатывает ведущие нули. Поскольку $machinenumber, который используется, должен иметь перед ним ноль в других целях, идея состоит в том, чтобы создать новую переменную ($nozero) на основе $machinenumber, где ведущие нули удаляются.Удаление ведущих нулей перед передачей переменной оболочки в другую команду

$machinenumber является двузначное число от 01 до 24. В настоящее время это 09

$machinetype 74 сейчас и не вызвало никаких проблем раньше.

То, что я до сих пор:

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

Хотя я считаю, что я на правильном пути, результаты кода в:

ERROR - Unknown string operation 

ответ

0

Мне пришлось пересмотреть этот код на днях из-за некоторых несвязанных вещей, и из-за совместимости с каким-либо другим программным обеспечением, которое читает один и тот же сценарий, мне было намного проще переписать его в это, что должно быть все еще справедливо Баш:

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

в основном, при добавлении 0 заставляют его быть истолкован как целое число, следовательно, автоматически зачисток ведущих нулей

+1

А? '($ machinenumber + 0)' не является синтаксисом math в bash. –

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

Try без пробелов вокруг = и с дополнительным знаком $.

18

Нет, вы делаете все (все права на все) правильными. Вы просто должны:

  • удалить пробелы вокруг =
  • использование $() или обратные кавычки вместо ()

Это было бы правильно:

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

Также вы должны использовать переменные без () вокруг них. Вы можете добавить "", если вы хотите:

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

И, конечно, переменные здесь не нужны. Вы можете просто сказать:

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

Это работает, приветствия. Что, если я хотел бы испечь его в команде iptables, tho? Я предпочитаю не объявлять никаких новых переменных. – Jarmund

+0

@Jarmund: он тоже будет работать. Было бы даже лучше muche –

+0

Не могли бы вы предоставить мне правильный синтаксис? Мои сценарии bash в лучшем случае изворотливы. – Jarmund

13

вы также можете сделать

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

Это оказался самый простой и эффективный подход: 'iptables -t nat -I POSTROUTING -s 10. ($ machinetype). ($ Machinenumber + 0) .0/24 - j MASQUERADE' – Jarmund

40

Вам не нужно использовать sed или другую внешнюю утилиту. Вот несколько способов, которыми Bash может разделить ведущие нули для вас.

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

В $(()) устанавливает контекст арифметический и 10# преобразует число от основания 10 к основанию 10 вызывает какие-либо начальные нули, чтобы быть отброшены.

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

Когда extglob включен, расширение параметра показано удаляет все ведущие нули. К сожалению, если исходное значение равно 0, результатом будет пустая строка.

+9

'10 #' - это самое простое и элегантное решение, которое я нашел до сих пор. Спасибо! – desgua

+0

'echo $ ((10 # $ {машинный номер}))' тоже работает в kornshell! Я искал не-багизм, и это должно работать нормально. ksh M-11/16/88f – bgStack15

+0

Он также работает в zsh. –

2

я сделать это с помощью

awk '{print $1 + 0}' 

я это нравится лучше, чем SED подход, как он все еще работает с числами, как 0, 000, и 001.

Таким образом, в вашем примере я заменил бы

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

с

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

8

Я не могу комментировать, так как у меня недостаточно репутации, но я предлагаю вам принять Dennis's answer (что действительно довольно аккуратно)

Во-первых, я не думаю, что ваш ответ действительно бас. В мою установку я получаю:

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

Если я цитирую его я получаю:

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

Я предполагаю, что вы имеете в виду:

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

Но, конечно, это все еще плохо раствор из-за восьмеричного:

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

Я предполагаю, что ваши цифры не являются 08 или 09 на данный момент.

Вот Денниса:

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

Правда, что в прошлом один может быть проблема проверки входных данных для кого-то.

СЕПГ решение имеет проблему:

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

> 
4

Чистый раствор Баш:

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

Это будет '[[" $ N "= ~^0 * (. +) $]] && N =" $ {BASH_REMATCH [1]} "' - это также работает для N = "000" и N = " 0" . Рассмотрим также '[[" $ N "= ~^0 * ([0-9] +) $]]' – Zrin

2

Я также не могу комментировать или голосовать все же, но ответ Дункан Ирвин является лучшим ,

Я хотел бы добавить примечание о переносимости. Синтаксис $((10#0009)) не переносится. Он работает в Баш и KSH, но не в тире:

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

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

Если портативность важна для вас, используйте SED ответ.

3

Использование СЭД:

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

В Баш это самый простой:

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

Значение б теперь "123". Общая форма: ${varname//find/replace} и заменяет любое количество вхождений find.

+0

Не будет ли это регулярное выражение удалять любые другие нули? И.Е. 0102030 => 123 – Jarmund

+0

Вы абсолютно правы. Он удаляет все вхождения. Итак, все, что я написал, было не ошибкой, хотя и не решая исходную проблему. :-) – gsl

1

Я бы сказал, что вы очень близко. Я не вижу требования, изложенного для bash, но ваша ненулевая логика ошибочна.

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

Добавление 0 является обычным методом для изменения номера строки в не-заполненное целое число. bc - базовый калькулятор. Я использую этот метод для удаления пространства и нулевого заполнения из чисел все время.

Хотя я не являюсь экспертом в синтаксисе iptables, я уверен, что скобки не нужны. Поскольку у меня уже есть символы без слов, граничащие с обеими переменными, мне не нужны специальные оболочки вокруг них. Символы слова;

[a-zA-z0-9_] 

Используя это решение, вы не теряете нуль в качестве потенциального значения и должны быть переносимыми по всем оболочкам.

 Смежные вопросы

  • Нет связанных вопросов^_^