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

Grep -P (pcre) How do I compare two values? #university_exercise

鉴于此数据

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)。

每个数字之间有一个space和3.2 = 03.20, 3.0 = 3

我试过了

grep -P '([1-9][0-9]*(?:\.[0-9]*[1-9])?)(\.?0*) ([A-Z]{3}) 0*(?!).* ' 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

我已经测试了我的解决方案,另外 returns:

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 时,它仍然不起作用,并且知道为什么。必须有一个否定。

使用awk非常简单,何必呢?

$ awk '!=' 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,因此比较很容易(即使浮点数比较有时很危险,但在您的情况下效果很好)

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

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

您可以使用这个有点复杂的正则表达式来完成这项任务:

grep -P '\h+0*(?:(?:(\d+)\.?0*\h+0*\.?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*\.?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*\.?0*\h+|(\d+\.\d*[1-9])0*\h+([A-Z]+)\h+\g{3}0*\h+)$)' 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