输入
AA XXX Y1Y ZZZ GG dhz
rr (AAAa) XXX Y2Y ZZZ TT GGGG UU
输出
Y1Y
Y2Y
输入行可能会有所不同。只有 Y1Y 之前的 XXX 和 Y1Y 之后的 ZZZ 是恒定的(它们是 XXX 和 ZZZ 的邻居,就像这样)。 Y1Y 可以是任何内容,例如:Y1Y、Y2Y、Y1T 等。
问:如何使用 awk 或 sed 或 grep 获取输出? (或者有更好的工具吗?)
更新(问题):为什么当有“.”时它不起作用在Y1Y?
[user@notebook ~] echo 'XXX Y1Y ZZZ' | grep -Po "(?<=XXX )(\w+)(?= ZZZ)"
Y1Y
[user@notebook ~] echo 'XXX Y1.Y ZZZ' | grep -Po "(?<=XXX )(\w+)(?= ZZZ)"
[user@notebook ~]
答案1
您可以使用grep
它提供的 PCRE 工具来执行此操作:
$ grep -Po "(?<=XXX )\S+(?= ZZZ)" data.txt
Y1Y
Y2Y
细节
该解决方案利用了PCRE的lookbehind和lookahead功能,可以匹配固定长度的字符串。
上面的内容是查看每个的后面,\w+
看看它是否是,XXX
以及每个的头部,\w+
看看它是否是ZZZ
。如果是,那么就匹配了。开关-o
告诉grep
它只打印匹配项,即\w+
.
后续,你可以用sed来做吗?
我不认为这个问题可以用 来解决sed
。我认为有两种方法。
- 将潜在的匹配保存在侧面变量中,如果遇到 ZZZ,则打印它们
- s/XXX ..我们的字符串.. ZZZ/ ..我们的字符串../
第一似乎是相当大量的工作,所以我什至不会尝试它。以下是方法 2 所发生的情况。
$ sed 's/.*XXX \(.*\) ZZZ.*/\1/' data.txt
Y1Y
Y2Y
AAAa YXX Y2Y ZZZ TT GGGG UU
所以它可以很好地找到匹配项,但对于不匹配的行它不会做任何事情。可能有一种方法可以指示sed
删除这些行,在这种情况下,这将是替代解决方案。