以下是示例 .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 表示多字符RS
、RT
和\s
的简写[:space:]
,可能就是您正在寻找的:
$ awk -v RS='\\s*ttt' 'RT && sub(/.*User\s*/,"")' file
abc (iii)
2023 defaa <party>
def (bbb)
20222 defaa <accoun>
如果您不想允许部分匹配User
,ttt
然后在它们周围添加单词边界:
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.*//