提取字符串之间的子字符串

问题描述

我有一个包含文本的文件,如下所示:

###interest1 moreinterest1### sometext ###interest2###
not-interesting-line
sometext ###interest3###
sometext ###interest4### sometext othertext ###interest5### sometext ###interest6###

我想提取 ###间的所有字符串。

我想要的输出是这样的:

interest1 moreinterest1
interest2
interest3
interest4
interest5
interest6

我尝试了以下方法

grep '###' file.txt | sed -e 's/.*###\(.*\)###.*/\1/g'

这几乎有效,但似乎只抓取每行的第一个实例,所以我输出中的第一行只抓取

interest1 moreinterest1

而不是

interest1 moreinterest1
interest2

解决方法

这是一个单独的 awk 命令来实现这一点,它使 ### 字段分隔符并打印每个偶数字段:

awk -F '###' '{for (i=2; i<NF; i+=2) print $i}' file

interest1 moreinterest1
interest2
interest3
interest4
interest5
interest6

这是一个替代 grep + sed 解决方案:

grep -oE '###[^#]*###' file | sed -E 's/^###|###$//g'

这假设 # 标记之间没有 ### 字符。

,

使用用于多字符 RS 的 GNU awk:

$ awk -v RS='###' '!(NR%2)' file
interest1 moreinterest1
interest2
interest3
interest4
interest5
interest6
,

您可以使用pcregrep

pcregrep -o1 '###(.*?)###' file

正则表达式 - ###(.*?)### - 匹配 ###,然后将除换行符以外的任何零或更多字符捕获到组 1 中,尽可能少,然后 ### 然后匹配 {{ 1}}。

### 选项将仅输出组 1 值。

参见regex demo online

,
sed 't x
s/###/\
/;D; :x
s//\
/;t y
D;:y
P;D' file

用换行符 D 替换“###”,然后如果“###”的第二次替换成功则有条件地分支到 P

,

这可能对你有用(GNU sed):

sed -n 's/###/\n/g;/[^\n]*\n/{s///;P;D}' file

用换行符替换所有出现的 ###

如果一行包含换行符,请删除第一个换行符之前和包括第一个换行符的所有字符,打印直到并包括以下换行符的详细信息,删除这些详细信息并重复。