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
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
编辑 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
鉴于此数据
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
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
编辑 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