在bash中最后一个点之后替换字符串


12

我在字符串(IP地址)中具有以下模式:

123.444.888.235

我想将圆点后的最后一个数字替换为0,因此它变为:

123.444.888.0

如何用bash其他Shell脚本语言来完成?


1
那些弦在哪里?在bash变量中?在文本文件中,每行一个吗?
斯特凡Chazelas

它在变量中。对不起,我忘了提。
2015年

3
如果这些是IP地址,则444和888是无效的八位位组值。
Digital Trauma 2015年

Answers:


24

在任何POSIX Shell中:

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

${var%pattern}ksh80年代引入的一种运算符,由POSIX标准化为标准sh语言,现在由所有解释该语言的shell实施,包括bash

${var%pattern}膨胀到的内容$var剥离匹配的最短串的图案关闭它的结束(或者以相同$var如果图案不匹配)。因此${var%.*}(其中.*模式表示点后跟任意数量的字符)扩展为$var没有最右边.以及后面的内容。相比之下,与模式匹配${var%%.*}最长字符串被剥离的位置将扩展为$var不包含最左侧.以及紧随其后的位置。


什么${var%.*}
声音

@ tjt263,在命令行中键入man bash并按Enter,然后键入/suffix pattern并按Enter。:)
通配符

在您的帖子之后添加了一些引号: 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。脚本本身只是一个简单的替换运算符,它将用替换行末的一个或多个数字0

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

相同的想法sed,使用[0-9]代替\d


如果您的字符串在变量中,并且您使用的外壳支持此处的字符串(例如bashzsh例如),则可以将以上内容更改为:

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() 将IP地址(或掩码)的点分十进制形式转换为简单整数
  • i2d() 做相反的事情-将简单的整数转换为点分十进制
  • ipmask()只需计算地址和网络掩码的按位与,即可得出地址的网络部分。Bash期望操作数为&整数。

这两个调用ipmask说明如何从两个不同的掩码的IP地址计算网络。


问题中指出的注释123.444.888.235是无效的IP地址。我已经用123.44.88.235这些例子代替了。


0

另一个sed答案:

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

它将所有内容分组到最后一个点,并用该组的内容后跟0替换整行。
我使用-r以避免转义括号。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.