我有一个使用多个选项构建的字符串:用 | 分隔的值
选项:值可以是以下两者之一:
[[:alnum:]]{3}:all
[[:alnum:]]{3}:FQDN
其中 FQDN 是主机的 DNS 名称
例如:
647:all|1bc:all|d1f:all|vf4:www.host.com|vk4:all|k22:www.another.com|bbd:all|opo:all
如何构建正则表达式来测试该字符串是否匹配规则?
答案1
您是否想测试该647:all|1bc:all|d1f:all|...
字符串的格式是否正确并且包含与您上面提到的模式匹配的部分?
根据您想要匹配域名的严格程度,其中一部分可能(在 ERE 中)例如
[[:alnum:]]{3}:(all|[-a-zA-Z0-9.]+)
还有一个包含多个副本的完整行,|
用 - 分隔:
^[[:alnum:]]{3}:(all|[-a-zA-Z0-9.]+)(\|[[:alnum:]]{3}:(all|[-a-zA-Z0-9.]+))*$
这将允许在域名中使用诸如abcd
或 之类的内容,即使它们不是真正完全限定或有效的名称。foo..bar
对于更严格的测试,域名部分可能应该是这样的:[-a-zA-Z0-9]+(\.[-a-zA-Z0-9]+)+\.?
首先拆分该字符串并单独测试各个部分,而不是使用单个大正则表达式,这可能会更漂亮。
像这样的东西会打印与所需模式不匹配的元素:
$ perl -lne 'chomp; for $a (split/\|/) {
print "mismatch: $a" if $a !~ /^[[:alnum:]]{3}:(all|[-a-zA-Z0-9]+(\.[-a-zA-Z0-9]+)+\.?)$/;
}' <<< '123:all|456:abcd|789:foo..bar|999:www.host.com'
mismatch: 456:abcd
mismatch: 789:foo..bar
答案2
以下两阶段管道将打印出字符串的所有部分不是满足问题中的标准:
tr '|' '\n'| sed -r -n '/^[[:alnum:]]{3}:[[:alnum:].]{1,}$/!p'
这对 FQDN 使用非常宽松/宽松的表达式: ,即任何字母数字以及,和[[:alnum:]._-]{1,}
的集合(这意味着 FQDN是“有效的”)。.
_
-
---
管道将字符串在分隔符上分成多行|
,并且sed
表达式打印与给定正则表达式不匹配的任何此类行(!p
“如果不匹配则打印”)。