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


12

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

123.444.888.235

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

123.444.888.0

どのようにして、bashまたは別のシェルスクリプト言語でそれを実行できますか?


1
それらの文字列はどこにありますか?bash変数では?テキストファイルで1行に1つですか?
ステファンChazelas

変数の中にあります。申し訳ありませんでした。
2015

3
それらがIPアドレスの場合、444と888は無効なオクテット値です。
Digital Trauma '21

回答:


24

任意のPOSIXシェル:

var=123.444.888.235
new_var="${var%.*}.0"

${var%pattern}ksh80年代に導入された演算子で、POSIXによって標準sh言語用に標準化されており、現在、その言語を解釈するすべてのシェルによって実装されていますbash

${var%pattern}末尾のパターンに$var一致する最短の文字列を取り除いた内容に展開します(または、そのパターンが一致しない場合と同じです)。だから、(ここで、あるパターンに展開手段は、任意の数の文字が続くドットという)は、一番右のなしとそれに従います。対照的に、パターンに一致する最長の文字列が取り除かれる場所は、左端がなく、それに続くものなしに展開されます。 $var${var%.*}.*$var.${var%%.*}$var.


なに${var%.*}

@ tjt263、コマンドラインタイプでman bash、Enterキーを押します、その後、入力/suffix patternし、Enterキーを押します。:)
ワイルドカード2015

あなたの投稿に続いていくつかの引用を追加しました: new_var="${var%.*}.0"... nJoy!。

8

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

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

sed置換の最後のフィールド\10は、最初に一致したパターン(\1)であり、リテラルのゼロで連結されていることに注意してください。


5

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

$ 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指示perlによって指定されたスクリプトを適用した後、各入力ラインを印刷します-e。スクリプト自体は、行末の1つ以上の数値をに置き換える単純な置換演算子0です。

$ echo 123.444.888.235 | sed 's/[0-9]*$/0/'
123.444.888.0

と同じ考え方sed、使用[0-9]代わりに\d


文字列が変数内にあり、ここで文字列bashまたはzshなど)をサポートするシェルを使用している場合、上記を次のように変更できます。

awk -F'.' -vOFS='.' '{$NF=0}1;' <<<$var
perl -pe 's/\d+$/0/' <<<$var
sed 's/[0-9]*$/0/' <<<$var

5

ネットマスクを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のオペランドは&整数であると想定しています。

ipmask2つの異なるマスクのIPアドレスからネットワークを計算する方法を示す2つの呼び出し。


質問に記載されているように、123.444.888.235無効なIPアドレスです。123.44.88.235これらの例では代わりに使用しました。


0

別のsed答え:

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

最後のドットまですべてをグループ化し、行全体をグループの内容の0で置き換え
ます。括弧をエスケープする必要がないように-rを使用しています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.