文字列(IPアドレス)に次のパターンがあります。
123.444.888.235
ドットの後の最後の数字を0
に置き換えたいので、次のようになります。
123.444.888.0
bash
または別のシェルスクリプト言語でどうすればよいですか?
任意のPOSIXシェル:
var=123.444.888.235
new_var="${var%.*}.0"
${var%pattern}
は、80年代にksh
によって導入された演算子であり、POSIXによって標準sh
言語用に標準化されており、bash
を含むその言語を解釈するすべてのシェルによって実装されています。
${var%pattern}
は、一致する最短の文字列を取り除いた$var
の内容に展開されますpatternの末尾から(またはpatternが一致しない場合は$var
と同じ)したがって、${var%.*}
(.*
はパターンであり、ドットの後に任意の数の文字が続くことを意味します)は、右端の$var
とそれに続くものなしで.
に展開されます。対照的に、パターンに一致する最長文字列が取り除かれた${var%%.*}
は、左端の$var
とそれに続くものなしで.
に展開されます。
これはうまくいくはずです。
echo 123.444.888.235 | sed 's/\([0-9]*\.[0-9]*\.[0-9]*\.\)[0-9]*/\10/'
sed
置換の最後のフィールド、\10
、最初に一致したパターン(\1
)、リテラル0と連結。
いくつかの方法(これらはすべて、文字列内の最後の数値セットを変更することを前提としています):
$ echo 123.444.888.235 | awk -F'.' -vOFS='.' '{$NF=0}1;'
123.444.888.0
ここで、-F'.'
はawk
に.
を入力フィールド区切り文字として使用し、-vOFS='.'
を出力フィールド区切り文字として使用するように指示します。次に、最後のフィールド($NF
)を0に設定して行を出力します(1;
はawk
の「現在の行を印刷する」の省略形です)。
$ echo 123.444.888.235 | Perl -pe 's/\d+$/0/'
123.444.888.0
-p
は、-e
で指定されたスクリプトを適用した後、各入力行を出力するようPerl
に指示します。スクリプト自体は、行の終わりにある1つ以上の数値を0
で置き換える単純な置換演算子です。
$ echo 123.444.888.235 | sed 's/[0-9]*$/0/'
123.444.888.0
[0-9]
の代わりに\d
を使用するsed
の同じアイデア。
文字列が変数にあり、 ここでは文字列 をサポートするシェル(たとえば、bash
またはzsh
など)を使用している場合、上記を次のように変更できます。
awk -F'.' -vOFS='.' '{$NF=0}1;' <<<$var
Perl -pe 's/\d+$/0/' <<<$var
sed 's/[0-9]*$/0/' <<<$var
入力がIPアドレスであり、そのアドレスの最後のオクテットを_.0
_で置き換えているとすると、私はあなたが何をしていると仮定します本当に達成しようとしているのはネットワーク部分を計算することです_255.255.255.0
_ネットマスクを使用したIPアドレスの。
ネットマスクの長さが8で割り切れる場合、オクテットをゼロで置き換えるだけで問題ありませんが、これは一般的なケースではありません。有効な(サブネット)ネットマスクに対してこの操作を実行する必要がある場合は、次のようにすることができます。
_function d2i() {
echo $(( 0x$( printf "%02x" ${1//./ } ) ))
}
function i2d() {
h=$( printf "%08X" "$1" )
echo $(( 0x${h:0:2} )).$(( 0x${h:2:2} )).$(( 0x${h:4:2} )).$(( 0x${h:6:2} ))
}
function ipmask() {
i2d $(( $( d2i $1 ) & $( d2i $2 ) ))
}
ipmask 123.44.88.235 255.255.255.0 # outputs 123.44.88.0
ipmask 123.44.88.235 255.255.255.240 # outputs 123.44.88.224
_
これは3つの関数を定義します:
d2i()
は、ドット付き10進形式のIPアドレス(またはマスク)を単純な整数に変換します。i2d()
はその逆です-単純な整数をドット付き10進数に変換しますipmask()
は、アドレスとネットマスクのビット単位のANDを計算するだけで、アドレスのネットワーク部分を提供します。 Bashは_&
_のオペランドが整数であることを期待します。ipmask
への2つの呼び出しは、2つの異なるマスクのIPアドレスからネットワークを計算する方法を示しています。
質問で述べたように、_123.444.888.235
_は無効なIPアドレスです。これらの例では、代わりに_123.44.88.235
_を使用しました。
代わりのsed
回答:
sed -r 's/(.*\.).*/\10/'
最後のドットまですべてをグループ化し、行全体をグループのコンテンツに置き換え、その後に0を続けます。
-rを使用して、括弧をエスケープする必要をなくしています。