我需要帮助用grep(我只能用grep)找出一个正则表达式,它将搜索一个文件,并显示从[a-f0-9]中的每个字符中精确包含2的行。
有效匹配示例:
33 e0 f1 76 9c 4f a8 6c 01 5d 45 9e 28 db 7b 2a
字符串
无效匹配示例:
c0 b0 f5 60 02 8b 1c a4 41 7c 53 f2 85 20 a0 d1
型
我尝试了'(?:[0-9a-f])?^[^\1]*\1[^\1]*\1[^\1]*$'
,但它显然不起作用,因为你不能否定这样的反向引用,即使我纠正了它,我也不确定这是正确的方法。
6条答案
按热度按时间krcsximq1#
你可以用一种简单的方式来做这件事,
字符串
sycxhyv72#
使用任何POSIX grep:
字符串
其中
regexlist
包含:型
这是使用De Morgan's law:
(A & B & C &.)== NOT(NOT(A)|非(B)|非(C)|......)的情况。
我们提供了一个必须失败的正则表达式的OR列表,然后使用grep的
-v
进行反转,这将产生一个必须匹配的正则表达式的AND列表。如果十六进制必须成对出现,则添加:
型
对于每个数字之间只有一个空格,并且行首或行尾没有空格:
型
如果您的
grep
支持-P
,则更简单。例如:型
^
....*$
-匹配整行(?!^.*?([0-9a-f]).*?\1.*?\1)
-不能包含三个(或更多)(?!^.*?[^0-9a-f ])
-仅十六进制和空格(?=[^ ]{2}( [^ ]{2}){15}$)
-正好16对或者,如果空白的数量是无关紧要的,甚至:
型
我相信锚定和懒惰:
型
应该比未锚定和/或贪婪更快地匹配(即失败):
6xfqseft3#
我想这是最简单的方法:
第一个月
基本上,它Assert行的开头后面没有出现3个或更多的相同字符,然后匹配空格分隔的字符对。
https://regex101.com/r/zerktu/1
5kgi1eie4#
我知道OP出于某种原因需要一个grep解决方案,但其他有类似问题的人在未来阅读这个问题可能不会有同样的限制。
给定这个输入,其中第一行是有效的,但最后3行涵盖了我认为的3种可能的失败情况(**1)input包含[0-9a-f]中的一个字符的少于2个,或者2)input包含不在[0-9a-f]中的一个字符,或者3)**input包含[0-9a-f]中的一个字符的多于2个):
字符串
记住this saying:
有些人在遇到问题时会想:“我知道,我会用正则表达式。”
下面是我真正的方法,在每个Unix机器上的任何shell中使用任何awk:
型
v1l68za45#
如果你必须只使用
grep
...那么我认为管道会使它更容易阅读和维护,尽管我不喜欢这个设计运行
grep
18次的事实。字符串
当然,您至少可以使用
sed
在一次传递中完成所有操作?型
您可能必须将这些命令单独放在一行中,但这样更好,而且可能更容易让下一个人理解。
zpf6vheq6#
下面是一个Perl一行程序的例子,它应该可以做到这一点:
字符串
此命令执行以下操作:
perl -ne
:为输入中的每一行添加以下Perl代码。/^[a-f0-9]*$/
:检查行是否只包含[a-f0-9]
范围内的字符。!grep {($_ =~ tr/$_//) != 2} 0..9,"a".."f"
:对于十六进制范围[a-f0-9]
中的每个字符,计算行($_ =~ tr/$_//
)中出现的次数。如果计数不正好为2,则字符通过grep过滤器。!
运算符将grep结果反转,因此只有当所有字符的计数都正好为2时,grep表达式才为true。print if
:如果grep表达式为true,则打印该行。此命令打印
file.txt
中仅包含十六进制字符且每个十六进制字符恰好出现两次的所有行。