![如何用虚拟 IP 地址替换与 IP 地址不匹配的字符串?](https://linux22.com/image/192341/%E5%A6%82%E4%BD%95%E7%94%A8%E8%99%9A%E6%8B%9F%20IP%20%E5%9C%B0%E5%9D%80%E6%9B%BF%E6%8D%A2%E4%B8%8E%20IP%20%E5%9C%B0%E5%9D%80%E4%B8%8D%E5%8C%B9%E9%85%8D%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%9F.png)
我有一个包含 IP 地址列表的文件,但有些字符串不是 IP 地址,我想用虚拟 IP 地址替换这些字符串。
我用它grep
来搜索IP;但不知道如何替换与虚拟 IP 地址不匹配的内容。我相信这可以通过 来完成sed
。我尝试了一些方法,但没有一个起作用。
cat file.txt | grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
我用它sed
来匹配文件中的 IP 地址,但我不知道如何用虚拟 IP 替换非 IP 地址。
sed -rn '/([0-9]{1,3}\.){3}[0-9]{1,3}/p' file.txt
输入:
192.168.10.20
00 03
10.28.214.5
192.168.10.40
BF
192.168.10.50
期望的输出:
192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50
谢谢!
答案1
您的正则表达式将匹配以下内容不是IPv4 点分四组地址,但看起来与它们相似(例如256.256.256.256
- 看起来很像 IPv4 地址,但事实并非如此)。
仅匹配有效的IPv4 地址,您需要使用正则表达式,例如:
(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
或(没有 perlish?:
非捕获组修饰符):
((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
这需要正确锚定,例如在两端使用^
和$
,或和。\b
\<
\>
看:正则表达式食谱作者:Jan Goyvaerts 和 Steven Levithan,由 O'Reilly Media, Inc. 出版
例如
$ sed -E '/^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/!s/.*/192.168.0.0/' file.txt
192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50
$ perl -p -e 's/.*/192.168.0.0/ unless m/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/' file.txt
192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50
这两者都会将整个输入行更改为 192.168.0.0,除非该行与有效的 IPv4 地址匹配。
就我个人而言,我会使用perl正则表达式::常见模块,它是用于常见模式匹配任务的正则表达式的大集合,可以方便地在名为%RE
.
$ perl -MRegexp::Common -p -e 's/.*/192.168.0.0/ unless m/^$RE{net}{IPv4}$/' file.txt
192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50
答案2
注意:其他人指出您为 IPv4 地址选择的正则表达式有缺陷。我不会尝试在这里解决这个问题,因为它在其他地方已经得到了很好的介绍。
你可以使用 sedC在与您的 RE不 ( !
) 匹配的行上执行hange 命令,例如。
$ sed -r '/([0-9]{1,3}\.){3}[0-9]{1,3}/!c\
192.168.0.0
' file.txt
192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50
使用 GNU sed,您可以简化为
sed -r '/([0-9]{1,3}\.){3}[0-9]{1,3}/!c192.168.0.0' file.txt
答案3
sed '/^\([[:digit:]]\{1,3\}\.\)\{3\}[[:digit:]]\{1,3\}$/!s/.*/192.168.0.0/' data
如果该行不是有效的 IPv4 地址,则将当前行替换为:192.168.0.0
。
我建议您使用另一个值作为虚拟地址,但这192.168.0.0
取决于您和您的需求。
或者相同但带有awk
:
awk '!/^([0-9]{1,3}\.){3}[0-9]{1,3}$/ {$0="192.168.0.0"}1' data
或者perl
:
perl -MNet::IP -ple '$_ = "192.168.0.0" unless new Net::IP($_)' data
答案4
和Perl
:
- 定义由一到三位数字组成的八位位组的正则表达式,并限制为非零前导,除非它是个位数。
- 匹配该行恰好包含 4 个由点分隔的八位字节。
- 将线分割成点,并且所有元组都小于 256。
dummy=192.168.0.0 \
perl -MList::Util=all -lpe '
$octet //= qr/(?!0\d)\d{1,3}/;
/^$octet(?:[.]$octet){3}$/ &&
all { $_<256 } split /[.]/ or
$_ = $ENV{dummy};
' file