web-dev-qa-db-ja.com

bashの最後のドットの後の文字列を置き換えます

文字列(IPアドレス)に次のパターンがあります。

123.444.888.235

ドットの後の最後の数字を0に置き換えたいので、次のようになります。

123.444.888.0

bashまたは別のシェルスクリプト言語でどうすればよいですか?

12
Ari

任意の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とそれに続くものなしで.に展開されます。

22

これはうまくいくはずです。

echo 123.444.888.235 | sed 's/\([0-9]*\.[0-9]*\.[0-9]*\.\)[0-9]*/\10/'

sed置換の最後のフィールド、\10、最初に一致したパターン(\1)、リテラル0と連結。

8
Kira

いくつかの方法(これらはすべて、文字列内の最後の数値セットを変更することを前提としています):

$ 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
5
terdon

ネットマスクをIPアドレスに適用する一般的なケース:

入力が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_を使用しました。

5
Digital Trauma

代わりのsed回答:

sed -r 's/(.*\.).*/\10/'

最後のドットまですべてをグループ化し、行全体をグループのコンテンツに置き換え、その後に0を続けます。
-rを使用して、括弧をエスケープする必要をなくしています。

0
Aaron