0

I have this source file.c:

#include <dir/header1>
#include <dir/header2>
#include <dir/header3>
...

I would like to match only those headers after dir, (e.g. header1). I do this:

$ sed -En 's/\/(.*)>/\1/p' file.c

but the will output:

#include <dirheader1, so it matched from the beginning of line, But I wanted to group from / character (therefor s/\/...). So I have tried:

$ sed -En 's/<.*\/(.*)>/\1/p' file.c

Neither that helped. So how to achieve that?

1
  • For clarity on what is expected, show us the output you are expecting from your sed command.
    – amisax
    May 11, 2020 at 20:23

2 Answers 2

0

To extract only the headerx bit of the three lines that you show with the s/// command in sed, you will have to remove all bits of the line that you don't want.

The bits of the line that you don't want is the initial #include <dir/ string at the start, and the final > string at the end. This must all be matched by your regular expression. Then also use a capture group for the bit in-between the initial and final strings to replace the whole line with the captured string:

sed -n 's,.*/\(.*\)>,\1,p' file.c

or, more explicitly,

sed -n 's,^#include <dir/\(.*\)>,\1,p' file.c
3
  • Why is need to match the whole line? for example, say if I have comments after >, then I would to what you said : sed -n 's,.*/\(.*\)>.*,\1,p' file.c , just added .*, after > so sed knows the line continue, but why is it needed? Perl does not need to slurp the whole line, it is sufficient for perl to just match, doesn't have to know look arounds. Why does sed needs to? May 11, 2020 at 18:20
  • @autistic456 You are correct about having to add .* to match the rest of the line in case there are comments, but there were none in your example. If you say s/a\(.*\)c/A\1C/ and apply that to the string abacus, I would expect it to result in AbaCus, not in AbaC, that is, the substitute command only substitutes the bit of the input string that matches the expression. I believe this to be true in Perl as well.
    – Kusalananda
    May 11, 2020 at 18:25
  • Ok, get it know, thanks May 11, 2020 at 18:32
0

You are not discarding the first part of the match so you could correct your code to do that.. as per @kusalananada

Alternatively a generic match using a negated pattern

sed -En "s|[^/]+/([^>]+)>|\1|p" file

For a specific match for #include

sed -En "s|^#include <dir/([^>]+)>|\1|p" file

Or with grep though you

grep -Po "(?<=#include <dir/)[^>]+" file

Or with gawk

awk -F"/|>" '$1~include{print $(NF-1)}' file

You must log in to answer this question.

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