选择两个重复的文本模式之间的所有文本或字符

选择两个重复的文本模式之间的所有文本或字符

以下是示例 .log 文件(其中可以有更多行)

2022 User abc (iii)
2023 defaa <party> ttt
2222221 User def (bbb)
20222 defaa <accoun> ttt
2222 User dddd (aaa)
3333 defaa <hahaha> jmd

我想选择User&之间的行ttt

请注意,这些类似于日志的 5-7 行,此日志中可以有更多行,由User&组成ttt

User所以我想知道一种方法来获取&之间的所有行,ttt即使它们在文件中重复

文本User&ttt并不总是在连续行上

预期输出:

abc (iii)
2023 defaa <party> 
def (bbb)
20222 defaa <accoun> 

如果是嵌套,则如下:

2022 User abc (iii)
2222221 User def (bbb)
20222 defaa <accoun> ttt
2023 defaa <party> ttt

预期输出:

def (bbb)
20222 defaa <accoun>

用户和 ttt 永远不会在同一行

答案1

使用 GNU awk 表示多字符RSRT\s的简写[:space:],可能就是您正在寻找的:

$ awk -v RS='\\s*ttt' 'RT && sub(/.*User\s*/,"")' file
abc (iii)
2023 defaa <party>
def (bbb)
20222 defaa <accoun>

如果您不想允许部分匹配Userttt然后在它们周围添加单词边界:

awk -v RS='\\s*\\<ttt\\>' 'RT && sub(/.*\<User\>\s*/,"")' file

答案2

使用sed,您可以选择一个地址范围User并将ttt其收集到保留空间中:

sed '/User/,/ttt/!d;H;/User/h;/ttt/!d;x;s/.*User //;s/ttt.*//' yourfile

详细解释:

  • /User/,/ttt/User选择从到下一个范围内的行ttt(如嵌套案例所要求的);该选择被反转!并被d删除。因此,此步骤将删除该范围之外的所有行。不幸的是,从文件最后User到结尾的最后一段是不是删除了,所以我们需要一种方法来摆脱它:
  • H将所有行追加到保留空间,同时/User/h 副本User到保留空间,因此保留空间包含从User到当前行的所有行。这样,新User行就会覆盖之前的所有内容,正如嵌套情况所预期的那样。
  • /ttt/!d停止所有没有 的行的执行ttt,因此我们不会生成任何输出,直到我们收集了User' to保存空间中 ttt` 的所有内容。
  • 但是,一旦我们把所有东西都放在一起,我们就可以x更改缓冲区,以将这些行从我们的模式空间中的保留空间中获取,
  • 然后删除所有User内容s/.*User //
  • 并删除从ttt以下内容开始的所有内容s/ttt.*//

相关内容