我需要用一定数量的数字替换一系列数字。我真的很难用sed编写代码(比如sed“s / [33-64] / 64 /”)或awk,但总是得到错误的结果。它倾向于替换单个数字而不是数字...我需要的是:替换0-32 - > 32,33-64 - > 64,65-128 - > 128,129-255 - > 255.在这些数字之间是IP,这应该保持不变。我认为这个命令选择了所有,但IP:
sed '/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/! ... '
所以我有一个这样的文件:
65.74.16.161
232
10.128.8.72
63
10.128.14.13
100
10.128.8.58
32
10.128.4.129
60
10.128.240.18
59
它应该是这样的:
65.74.16.161
255
10.128.8.72
64
10.128.14.13
128
10.128.8.58
32
10.128.4.129
64
10.128.240.18
64
答案 0 :(得分:3)
[33-64]
定义了一个字符类,是一种写[3-6]
的有趣方式,确实只匹配一个字符 - 来自3,4,5或6的任何单个数字。如果你真的想要使用sed
执行此操作,并且您关注的是33到64之间的值,那么您必须以不同的方式编写它 - 并且更加冗长。
部分取决于您拥有的sed
版本。适用于经典sed
的解决方案是:
sed -e 's/^[0-9]$/32/' \
-e 's/^[12][0-9]$/32/' \
-e 's/^3[012]$/32/' \
-e 's/^3[3-9]$/64/' \
-e 's/^[45][0-9]$/64/' \
-e 's/^6[0-4]$/64/' \
-e 's/^6[5-9]$/128/' \
-e 's/^[7-9][0-9]$/128/' \
-e 's/^1[01][0-9]$/128/' \
-e 's/^12[0-8]$/128/' \
-e 's/^129$/255/' \
-e 's/^1[3-9][0-9]$/255/' \
-e 's/^2[0-4][0-9]$/255/' \
-e 's/^25[0-5]$/255/'
但是,正如你所看到的,这是非常痛苦的。如果您有GNU sed
,则可以使用-r
选项启用扩展正则表达式;如果您使用的是Mac OS X或BSD sed
,则可以使用-E
选项启用扩展正则表达式。然后,您可以将上面的代码缩减为:
sed -E \
-e 's/^([0-9]|[12][0-9]|3[012])$/32/' \
-e 's/^(3[3-9]|[45][0-9]|6[0-4])$/64/' \
-e 's/^(6[5-9]|[7-9][0-9]|1[01][0-9]|12[0-8])$/128/' \
-e 's/^(129|1[3-9][0-9]|2[0-4][0-9]|25[0-5])$/255/'
但是,使用awk
:
awk '/^[0-9][0-9]*$/ { if ($1 <= 32) print 32
else if ($1 <= 64) print 64
else if ($1 <= 128) print 128
else if ($1 <= 255) print 255
else print $1
next
}
{ print }'
最终的else
子句准确地打印出任何意外的值,例如256或999,或者实际上是123456789.有些人会用1
来代替{ print }
- 部分匹配并打印IP地址的awk
脚本。
答案 1 :(得分:1)
您可以使用此awk
进行一些算术运算:
awk '$1 == ($1+0) && $1<=255{$1 = ($1>128)?255:($1>64?128:32 * int(($1+31)/32))} 1' file
65.74.16.161
255
10.128.8.72
64
10.128.14.13
128
10.128.8.58
32
10.128.4.129
64
10.128.240.18
64
$1 == ($1+0)
是一项检查,用于确定$1
是一个整数。
答案 2 :(得分:0)
使用awk:
awk -vFS=. ' NF == 1 { v=2^int((log($1)/log(2))+0.5); $1 = v>255?255:v; }1' input
给出:
65.74.16.161
255
10.128.8.72
64
10.128.14.13
128
10.128.8.58
32
10.128.4.129
64
10.128.240.18
64