Data (some-mutool-clean-pdf-file) to operate on is something like the following, whilst leading numbers are not part of the data, but hopefully serve to clarify my problem:

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)..
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

The dots stand for \d or [ or ] or TJ etc. and should be prevented from printing.

Desired Result:

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

The following command does approximately what I'd like to achieve except for a lack of "multiple start patterns". I am sure there is / are a better / different way / ways, but that is the way I was able to snip together.

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'

Here is what I imagine how it could work. Unfortunately it doesn't, but hopefully it shows what I'd like to achieve ("multiple start patterns" with one single "end match" - I hope I name it appropriately).

Here "multiple start patterns" means explicitly: /H1 <<MCID or /Span <<MCID, while both end with EMC. It is not to be achieved to match something like that: /any_tag <<MCID, while there are tags different from H1 or Span. The letters between parenthesis should alwas be printed and in every range there are (letter) patterns - but also in ranges starting with other tags, which should not be printed.

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'

Any help is highly appreciated. Thanks in advance!

  • Welcome to the site. Unfortunately, the task is not entirely clear. You speak of "start" and "end" patterns. What exactly is the start pattern? Any /some_tag <</MCID line, or only such lines with specific tags? What is the end pattern? EMC? Also, what exactly is the task? Print everything within the parentheses when between the start and end patterns, and including line numbers - or are they, too, only for illustration. While in principle it might be possible to deduce it from your example sed commands, it would be better to explicitly state these conditions in the question test.
    – AdminBee
    Sep 18, 2020 at 7:04
  • Hello, and thanks! Yes the start pattern is only such lines with specific tag, such as H1 or Span. Yes, the end pattern is EMC in both cases. Yes please: Print everything within the parenthesis when between the start and end patterns, and including line numbers.
    – andtoe
    Sep 18, 2020 at 7:15
  • Relevant point: Can there be lines /<tag> <</MCID with tags that should not be considered a start pattern. In other words, does every line of that form constitute a start pattern, or only those where the tag is H1 or Span. Does it have to be sed, or is awk also a possibility? Do all lines in between the start and end patterns contain the ( letter ) content? Also, when replying to comments asking for clarification, please edit your question to include the details, don't use (only) comment replies to answer.
    – AdminBee
    Sep 18, 2020 at 7:17
  • Yes. Indeed. The pattern should only match the said two of all possible tags. There are more possible tags than only H1 and Span, ineed. Those tags should not match. Awk would also be fine, but since I have started with sed I am also interessted in an approach with sed, if possible. Yes ( letter ) content is alway between these lines. Yes I will include the details and edit my initial question regarding additional information in comments.
    – andtoe
    Sep 18, 2020 at 7:28

1 Answer 1


The following is an awk solution. It requires GNU awk for the gensub() function:

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

This will set a flag s to 1 when the start pattern was found, defined as a line starting with /Span OR /H1, followed by and ending with <</MCID. The flag will be reset if a line consisting of EMC is found.

Inside the region (i.e. when s is 1), use the gensub() function to replace any occurence of the pattern "any number of characters that are not a (, followed by one character in ( ), followed by any number of characters that are not a (", by the character contained in the ( ). It then prints the current line number and the extracted text.

Note that this implies there are no lines which do not contain that kind of pattern between start and end lines.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .