![将网络掩码应用于 IP 地址的一般情况:](https://linux22.com/image/79883/%E5%B0%86%E7%BD%91%E7%BB%9C%E6%8E%A9%E7%A0%81%E5%BA%94%E7%94%A8%E4%BA%8E%20IP%20%E5%9C%B0%E5%9D%80%E7%9A%84%E4%B8%80%E8%88%AC%E6%83%85%E5%86%B5%EF%BC%9A.png)
我的字符串(IP 地址)中有以下模式:
123.444.888.235
我想用 替换点后的最后一个数字0
,所以它变成:
123.444.888.0
我怎样才能用bash
或其他 shell 脚本语言来做到这一点?
答案1
在任何 POSIX shell 中:
var=123.444.888.235
new_var="${var%.*}.0"
${var%pattern}
ksh
是80 年代引入的运算符,由 POSIX 针对标准sh
语言进行标准化,现在由解释该语言的所有 shell 实现,包括bash
.
${var%pattern}
$var
扩展为stripped 的最短匹配字符串的内容图案离开它的末尾(或者就像$var
那样图案不匹配)。所以${var%.*}
(哪里.*
是图案这意味着点后跟任意数量的字符)扩展到$var
没有最右边.
及其后面的内容。相比之下,${var%%.*}
其中最长与被剥离模式匹配的字符串将扩展为$var
没有最左边.
及其后面的内容。
答案2
这应该有效。
echo 123.444.888.235 | sed 's/\([0-9]*\.[0-9]*\.[0-9]*\.\)[0-9]*/\10/'
请注意,最后一个sed
替换字段\10
是第一个匹配的模式 ( \1
),与文字零连接。
答案3
将网络掩码应用于 IP 地址的一般情况:
假设你输入的是 IP 地址,并且你用 替换该地址的最后一个八位字节.0
,那么我假设你是真的试图实现的是使用网络掩码来计算 IP 地址的网络部分255.255.255.0
。
如果您的网络掩码长度可以被 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
这些例子来代替。
答案4
另一种sed
答案:
sed -r 's/(.*\.).*/\10/'
它将所有内容分组到最后一个点,并将整行替换为该组的内容,后跟 0。
我使用 -r 来避免必须转义括号。