sed - 删除点的每个实例前面的所有数字

sed - 删除点的每个实例前面的所有数字

我试图去掉下面几个 IP 范围前面的数字:

range 1.1.1.10 1.1.1.100;

我想显示以下输出:

IP range is: 10-100

当我尝试这个命令时:

echo '  range 1.1.1.10 1.1.1.100;' | sed -rn '/^\s*range/ s/.*\.([0-9]{1,3})\s*.*\.([0-9]{1,3});/IP range is: \1-\2/p'

我得到:

IP range is: 1-100

但是当我尝试这个命令时

echo '  range 1.1.1.10 1.1.1.100;' | sed -rn '/^\s*range/ s/.*\.([0-9]{1,3})\s*.*([0-9]{1,3});/IP range is: \1-\2/p'

我得到:

IP range is: 10-0

我错过了什么吗?在我看来, sed 不会在第一个地址中最后一个八位字节出现后立即寻找空格。

答案1

你的问题与贪婪有关.*。您仍然可以在 中执行此操作sed,但使用 Perl 更容易:

$ echo 'range 1.1.1.10 1.1.1.100;' | perl -ne 'printf("IP range is %d-%d\n", (/\.(\d+)[^.]/g))'
IP range is 10-100

Perl 脚本匹配 IP 地址末尾的数字,并将它们作为两个整数返回,用于printf()打印格式化的输出字符串。

Perl 正则表达式

/\.(\d+)[^.]/g

将捕获前面有一个点但后面没有点的每组数字。


sed实际上不必一次性进行替换:

$ echo 'range 1.1.1.10 1.1.1.100;' | sed -E -e 's/[^ ]*\.([0-9]+);/\1/'
range 1.1.1.10 100

$ echo 'range 1.1.1.10 1.1.1.100;' | sed -E -e 's/[^ ]*\.([0-9]+);/\1/' -e 's/[^ ]*\.([0-9]+) /\1-/'
range 10-100

$ echo 'range 1.1.1.10 1.1.1.100;' | sed -E -e 's/[^ ]*\.([0-9]+);/\1/' -e 's/[^ ]*\.([0-9]+) /\1-/' -e 's/range/IP & is/'
IP range is 10-100

最终sed脚本:

s/[^ ]*\.([0-9]+);/\1/;   # Isolate last number in range
s/[^ ]*\.([0-9]+) /\1-/;  # Isolate first number in range, add dash
s/range/IP & is/;         # Sort out text at start

经过检查,可以缩短为

s/[^ ]*\.([0-9]+)[^.]/-\1/g
s/range -/IP range is /

那是

$ echo 'range 1.1.1.10 1.1.1.100;' | sed -E -e 's/[^ ]*\.([0-9]+)[^.]/-\1/g' -e 's/range -/IP range is /'
IP range is 10-100

答案2

用gnu sed 不控制行的有效性

sed -E 's/.*\.(\S+)\s+.*\.(\S+);.*/IP range is: \1-\2/'

答案3

sed -r '/^[[:blank:]]*range[[:blank:]]+/ {
    s///                 # delete the previous match, "range"
    s/;.*//
    s/[[:digit:]]+\.//g  # remove digits followed by dot
    s/[[:blank:]]+/-/
    s/^/IP range is: /
}' <<END
range 1.1.1.10 1.1.1.100;
END
IP range is: 10-100

答案4

$ echo '   range 1.1.1.10 1.1.1.100;' |
  sed -Ene 's/^[[:blank:]]*range [0-9.]*\.([0-9]+) [0-9.]*\.([0-9]+);.*/IP range is: \1-\2/p'
IP range is: 10-100

部分:

^[[:blank:]]*        any blanks at start of line
[0-9.]*\.            numbers and dots, ending with a dot 
([0-9]+)             capture the following numbers
[0-9.]*\.([0-9]+)    same, again
\1  and  \2          put back the captured groups

s///p                print if the substitution matched 

相关内容