如何只输出具有恒定邻居的列?

如何只输出具有恒定邻居的列?

输入

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。我认为有两种方法。

  1. 将潜在的匹配保存在侧面变量中,如果遇到 ZZZ,则打印它们
  2. s/XXX ..我们的字符串.. ZZZ/ ..我们的字符串../

第一似乎是相当大量的工作,所以我什至不会尝试它。以下是方法 2 所发生的情况。

$ sed 's/.*XXX \(.*\) ZZZ.*/\1/' data.txt 
Y1Y
Y2Y
AAAa YXX Y2Y ZZZ TT GGGG UU

所以它可以很好地找到匹配项,但对于不匹配的行它不会做任何事情。可能有一种方法可以指示sed删除这些行,在这种情况下,这将是替代解决方案。

相关内容