我试图去掉下面几个 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