根据模式提取字符,但仅在两个范围起始模式和一个公共结束模式之间提取字符

根据模式提取字符,但仅在两个范围起始模式和一个公共结束模式之间提取字符

要操作的数据(some-mutool-clean-pdf-file)如下所示,虽然前导数字不是数据的一部分,但希望有助于澄清我的问题:

1 blabla
2 /Span <</MCID
3 .(s).(o)..(m).(e)...(c).(h)..(a)...(r)..
4 .(s).(o)..(m).(e)...(c).(h)...(a)..(r)..
5 .(s).(o)..(m).(e)...(c).(h)..(a)...(r)..
6 EMC
7 blabla
8 blabla
9 blabla
10 /H1 <</MCID
11 .(s).(o)..(m).(e)...(c).(h)..(a)...(r)..
12 .(s).(o)..(m).(e)...(c).(h)...(a)..(r)..
13 .(s).(o)..(m).(e)...(c).(h)..(a)...(r)..
14 EMC
15 blabla

这些点代表\d“or”[或“ ]or”TJ等,应避免打印。

期望的结果:

3 somechar
4 somechar
5 somechar
11 somechar
12 somechar
13 somechar

除了缺少“多个启动模式”之外,以下命令大致完成了我想要实现的目标。我确信有更好的/不同的方式,但这就是我能够剪辑在一起的方式。

sed -n '/\/H1\ <<\/MCID/,/EMC/{=;p}' somepdffile |  sed '{N;s/\n/ /}' | sed -n 's/\[\(.*\)\]/...\1.../p' | sed 's/(\|)\|\.\|TJ\|-//g' | sed -r
> 's/(^[0-9]*)*[0-9]*/\1/g'

这是我想象的它是如何工作的。不幸的是它没有,但希望它展示了我想要实现的目标(“多个开始模式”和一个“结束匹配” - 我希望我正确地命名它)。

这里“多个开始模式”明确表示:/H1 <<MCID/Span <<MCID,而两者都以 结尾EMC。无法实现匹配这样的内容:/any_tag <<MCID,而存在与H1或不同的标签Span。括号之间的字母应该始终被打印,并且在每个范围中都有模式 - 但在以其他标签开头的范围中也应该不被打印。(letter)

sed -n '/\/H1\ <<\/MCID\|\/Span\ <<\/MCID/,/EMC/{=;p}' somepdffile |  sed '{N;s/\n/ /}' | sed -n 's/\[\(.*\)\]/...\1.../p' | sed 's/(\|)\|\.\|TJ\|-//g' | sed -r 's/(^[0-9]*)*[0-9]*/\1/g'

非常感谢任何帮助。提前致谢!

答案1

下面是一个awk解决方案。它需要 GNU awk 来实现该gensub()功能:

awk '$0=="EMC" {s=0} s{print FNR, gensub(/[^(]*\((.)\)[^(]*/, "\\1", "g")} /^\/(Span|H1) <<\/MCID$/ {s=1}' test.pdf

s当找到起始模式时,这会将标志设置为 1,起始模式定义为以/SpanOR开头/H1、后跟并以 结尾的行<</MCID。如果EMC找到包含以下内容的行,则该标志将被重置。

在该区域内(即当s为 1 时),使用该gensub()函数将任何出现的模式“任意数量的非 a 字符(,后跟 中的一个字符( ),后跟任意数量的非 a 字符(”替换为中包含的字符( )。然后它打印当前行号和提取的文本。

笔记这意味着有起始行和结束行之间不包含这种模式的行。

相关内容