我在字符串(IP地址)中具有以下模式:
123.444.888.235
我想将圆点后的最后一个数字替换为0
,因此它变为:
123.444.888.0
如何用bash
其他Shell脚本语言来完成?
我在字符串(IP地址)中具有以下模式:
123.444.888.235
我想将圆点后的最后一个数字替换为0
,因此它变为:
123.444.888.0
如何用bash
其他Shell脚本语言来完成?
Answers:
在任何POSIX Shell中:
var=123.444.888.235
new_var="${var%.*}.0"
${var%pattern}
是ksh
80年代引入的一种运算符,由POSIX标准化为标准sh
语言,现在由所有解释该语言的shell实施,包括bash
。
${var%pattern}
膨胀到的内容$var
剥离匹配的最短串的图案关闭它的结束(或者以相同$var
如果图案不匹配)。因此${var%.*}
(其中.*
的模式表示点后跟任意数量的字符)扩展为$var
没有最右边.
以及后面的内容。相比之下,与模式匹配${var%%.*}
的最长字符串被剥离的位置将扩展为$var
不包含最左侧.
以及紧随其后的位置。
${var%.*}
man bash
并按Enter,然后键入/suffix pattern
并按Enter。:)
new_var="${var%.*}.0"
... nJoy!。
几种方法(所有这些方法都假定您要更改字符串中的最后一组数字):
$ 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
。脚本本身只是一个简单的替换运算符,它将用替换行末的一个或多个数字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
假设您输入的是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()
将IP地址(或掩码)的点分十进制形式转换为简单整数i2d()
做相反的事情-将简单的整数转换为点分十进制ipmask()
只需计算地址和网络掩码的按位与,即可得出地址的网络部分。Bash期望操作数为&
整数。这两个调用ipmask
说明如何从两个不同的掩码的IP地址计算网络。
问题中指出的注释123.444.888.235
是无效的IP地址。我已经用123.44.88.235
这些例子代替了。