Grep -P(pcre)如何比较两个值? #university_exercise

时间:2016-11-12 16:54:41

标签: regex grep pcre

鉴于此数据

A 1.20 GBP 1.2 GBP
B 1.2 GBP 1.20 GBP
C 01 GBP 1 GBP
D 1 GBP 01 GBP
E 1.0 GBP 1 GBP
F 1 GBP 1.0 GBP
G 2.10 GBP 3.2 GBP
H 4.1 GBP 3.20 GBP
I 04 GBP 3 GBP
J 4 GBP 03 GBP
K 4.0 GBP 3 GBP
L 4 GBP 3.0 GBP

我必须找到值不同的行(使用grep -P)。

每个号码之间只有一个空格,3.2 = 03.20, 3.0 = 3

我试过这个

grep -P '([1-9][0-9]*(?:\.[0-9]*[1-9])?)(\.?0*) ([A-Z]{3}) 0*(?!\1).* \3' filename

不幸的是它似乎没有正常工作。我实际上并不确定否定前瞻。

编辑:

我知道有很多更好的方法可以达到这个结果。

但是我是学生,这是我必须用正则表达式使用grep做的练习。

我尝试过的工作直到它得到更棘手的测试,所以如果你能提供帮助,那就告诉我我做错了什么。

结果应为:

G 2.10  GBP 3.2 GBP
H 4.1 GBP 3.20 GBP
I 04 GBP 3 GBP
J 4 GBP 03 GBP
K 4.0 GBP 3 GBP
L 4 GBP 3.0 GBP

我已经测试了我的解决方案,它还会返回:

A 1.20 GBP 1.2 GBP
B 1.2 GBP 1.20 GBP
D 1 GBP 01 GBP

我还检查了https://regex101.com/中的正则表达式。结果令人惊讶,因为对于A行和B行,正则表达式只占用了句点后的数字。检查一下,知道我在说什么。

对于那些讲述grep -v的人的另一个编辑: 我没有提出整个运动。在每个数字之后,还有其他东西必须相同,所以当我使用grep -v时,它仍然不起作用而且它已知原因。必须有一个否定。

3 个答案:

答案 0 :(得分:2)

使用awk非常简单,为什么要这么麻烦?

$ awk '$2!=$4' input.txt

结果:

G 2.10 GBP 3.2 GBP
H 4.1 GBP 3.20 GBP
I 04 GBP 3 GBP
J 4 GBP 03 GBP
K 4.0 GBP 3 GBP
L 4 GBP 3.0 GBP

awk会自动将值处理到float中,因此比较很容易(即使浮动比较有时很危险,在您的情况下也很有效)

答案 1 :(得分:1)

您可以使用此位复杂正则表达式执行此任务:

grep -P '\h+0*(?:(?:(\d+)\.?0*\h+0*\1\.?0*|(\d+\.\d*[1-9])0*\h+\g{2}0*)(*SKIP)(*F)|.*)$' file

G 2.10 3.2
H 4.1 3.20
I 04 3
J 4 03
K 4.0 3
L 4 3.0

RegEx Demo

PCRE动词(*SKIP)(*F)用于在交替中跳过匹配。

另外,你也可以使用这个负前瞻性正则表达式:

grep -P '^\S+\h+(?!0*(?:(\d+)\.?0*\h+0*\1\.?0*|(\d+\.\d*[1-9])0*\h+\g{2}0*)$)' file

G 2.10 3.2
H 4.1 3.20
I 04 3
J 4 03
K 4.0 3
L 4 3.0

RegEx Demo 2

编辑2 :要包含货币以及使用:

grep -P '^\S+\h+(?!0*(?:(\d+)\.?0*\h+([A-Z]+)\h+0*\1\.?0*\h+\2|(\d+\.\d*[1-9])0*\h+([A-Z]+)\h+\g{3}0*\h+\4)$)' file

G 2.10 GBP 3.2 GBP
H 4.1 GBP 3.20 GBP
I 04 GBP 3 GBP
J 4 GBP 03 GBP
K 4.0 GBP 3 GBP
L 4 GBP 3.0 GBP

RegEx Demo 3

答案 2 :(得分:0)

可能有一个更简单的解决方案。这是相当丑陋的,但它完成了工作

grep -v -P '\s+0*(\d+(?:\.\d*[1-9])?)[.0]*\s+0*\1[.0]*\b' filename