web-dev-qa-db-ja.com

シェル変数を別のコマンドに渡す前に先行ゼロを削除する

Iptablesは先行ゼロをうまく処理していないことがわかります。使用される$machinenumberは、他の目的のために先行ゼロを持たなければならないため、$nozeroに基づいて新しい変数($machinenumber)を作成するだけです。離れて。

$machinenumberは01から24までの2桁の数字です。現在は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
38
Jarmund

関係のないものがあるため、先日このコードを再確認しなければならず、同じスクリプトを読み取る他のソフトウェアとの互換性のため、これを書き換えるのが最も簡単であることがわかりました。

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

基本的に、0を追加すると強制的に整数として解釈されるため、先行ゼロが自動的に削除されます

0
Jarmund

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の場合、結果はNULL文字列になります。

53

いいえ、すべて(ほとんどすべて)を正しくします。あなたはただする必要があります:

  • _=_の周りのスペースを削除します
  • _()_の代わりに$()またはバックティックを使用します

それは正しいでしょう:

_ 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
_
22
Igor Chubin

あなたもできる

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

私は十分な評判がないのでコメントすることはできませんが、受け入れることをお勧めします デニスの答え (これは非常にきれいです)

第一に、あなたの答えが有効なバッシュだとは思いません。私のインストールで私は得る:

> 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

しかし、もちろん、8進数のため、それはまだ悪い解決策です。

> 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

確かに、最後の問題は誰かにとっての入力検証の問題かもしれません。

Sedソリューションには次の問題があります。

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

>
8
Duncan Irvine
nozero=$(echo $machinenumber | sed 's/^0*//')

=の前後にスペースを入れずに、$記号を追加してみてください。

6
Balint

純粋なbashソリューション:

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

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
4
Jahid

私はそれを使ってそれをします

awk '{print $1 + 0}'

0、000、001などの数値でも機能するため、sedアプローチよりもこの方法の方が好きです。

だからあなたの例では私は置き換えます

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

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

まだコメントしたり投票したりすることもできませんが、ダンカンアーバインの答えが最高です。

移植性に関するメモを追加したいと思います。 $((10#0009))構文は移植できません。 bashとkshで機能しますが、ダッシュでは機能しません。

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

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

移植性が重要な場合は、sed回答を使用してください。

2
Aurelio Jargas

私はあなたが非常に近いと言います。 bashの要件は記載されていませんが、非ゼロロジックには欠陥があります。

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

0を追加することは、文字列番号を非埋め込み整数に変更する一般的な方法です。 bcは基本的な計算機です。この方法を使用して、常に数字からスペースとゼロパディングを削除します。

私はiptables構文の専門家ではありませんが、括弧は必要ないと確信しています。両方の変数に接する非Word文字が既にあるので、それらの周りに特別な囲いは必要ありません。単語の文字は次のとおりです。

[a-zA-z0-9_]

このソリューションを使用すると、潜在的な値としてゼロが失われることはなく、すべてのシェルで移植可能になります。

1
Daniel Liston

Bashを使用している場合、これは最も単純なように見えます。

nozero=$(bc<<<$machinenumber)
1
Cyker

0の数値を追加すると、先行ゼロが削除されます

eg: expr 00010 + 0 #becomes 10

OR

num=00076
num=${num##+(0)}
echo $num
0
Aashutosh

Sed、awk、またはPerlがない場合は、cutおよびgrepを使用できます

mn="$machinenumber"
while echo "$mn"|grep -q '^0';do mn=$(echo "$mn"|cut -c2-);done
iptables -t nat -I POSTROUTING -s 10.($machinetype).($mn).0/24 -j MASQUERADE

Bashとdashシェルの両方で動作します。

0
Alexx Roche