7

I have a sed command that I want to use in a Makefile. It works in the terminal. The command is

sed -n '/[{]/,/[}]/{
p
/[}]/a\
 //end of block matching brace
}' myfile.txt

This results in these error messages from make:

/bin/sh: 2: Syntax error: Unterminated quoted string

If I add backslashes or place everything on one line I get

sed: -e expression #1, char 14: extra characters after command

Any help would be greatly appreciated.

4
  • Does it work if you escape all newlines and the \ that occurs at the end of one of the lines, so that you have a\\\ on that line? – Kusalananda Apr 19 '20 at 11:16
  • Won't awk '/[{]/,/[}]/{print; if($0~/[}]/)print "//end of ..."}' do the same and fit on a single line? There probably are ways to achieve what you're trying to do, but I'm not able to figure out any standard way to do it. – mosvy Apr 19 '20 at 11:32
  • @Kusalananda No. – mosvy Apr 19 '20 at 11:43
  • @mosvy Yes, that worked! Thank you so much. I only had to use two dollar signs instead of one. – Theo Apr 19 '20 at 12:10
3

Try

$ sed -n -e '/[{]/,/[}]/{p; /[}]/ a\ //end of block matching brace' -e' }' file
{sdfg
If I add backslashes or place everything on one line I get
df }
 //end of block matching brace

Be aware of the TWO -e (expression) options needed because you need to terminate the append text. Not all sed versions allow for append text in the same line (my GNU sed does, my FreeBSD sed does not).

6
  • For BSD sed divide the a command up into two expressions, one ending a\ and one beginning //end. – Kusalananda Apr 19 '20 at 12:07
  • Thank you! This works, but I think I will use @mosvy 's answer, as since its more portable. – Theo Apr 19 '20 at 12:19
  • @ Kusalananda: unfortunately, I get an error message with your hint: sed: 1: "//end of block matching ...": invalid command code e – RudiC Apr 19 '20 at 12:24
  • @RudiC Did you forget the -e? sed -n -e '/[{]/,/[}]/{p; /[}]/ a\' -e '//end of block matching brace' -e '}' – Kusalananda Apr 19 '20 at 13:10
  • @Theo mosvy hasn't submitted an answer, but you could use it in a self-answer if you also explained it. – Kusalananda Apr 19 '20 at 13:11
2

Whenever I am struggling with newlines, backslashes esp in makefiles, I reach for the G command in sed. What's more, it allows one to remain within Posix sed:

$ sed -e '/[{]/,/[}]/!d' -e '/[}]/G' -e 's|\n|&//end of block matching brace|' myfile.xt
2
  • My sed-fu isn't as strong as yours... what's special about G please? – roaima Apr 21 '20 at 23:24
  • 1
    One doesn't need to slip in an escaped newline in the RHS of s/// and then the sed expression can be single lined. All this n still posixly. – Rakesh Sharma Apr 22 '20 at 15:25
1

With gnu make and a shell that accepts $'' you can use an intermediate variable as make handles \eol differently outside recipes:

make  -f - <<\!
define mycmd
sed -n $$'/[{]/,/[}]/{\n\
p\n\
/[}]/a\\\n\
 //end of block matching brace\n\
}' myfile.txt
endef

.PHONY: default
default:
        $(mycmd)
!

Each line had \n\ added, and the solitary \ was doubled. Make converts the \eol outside recipes into a space, so it all ends up on one line, then the shell $'' converts the \n into real newlines. You don't have to use define to set the variable; MYCMD = sed... works similarly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.