3

I'm using eclipse on Windows to build a C-project. I create a preprocessor define containing git status summary git status -s.

This is my define symbol:

GIT_STATUS="$(shell git status -s)"

This works, but if changed files contain spaces those paths are surrounded by un-escaped quotes.

example:

git status -s
 M file1.c
 M "file 2.c"

expected output:

'-DGIT_STATUS="M file1.c \"file 2.c\""'

In the command-line I can use sed to escape these quotes:

git status -s | sed 's/"/\\"/g'

or

git status -s | sed 's/\x22/\\"/g'

This works. But if I use this in define symbol it doesn't work.

I can replace characters such as a and b:

GIT_STATUS="$(shell git status -s | sed "s/a/b/g")"

But if I add a double quote it won't work. Even if I escape it once or twice or three times.

I either get sed: bad option in substitution expression or an empty string as value for the define.

So now I use a separate file as a workaround:

GIT_STATUS="$(shell git status -s | sed -f ../replace_quotes.sed)"

containing:

s/"/\\\"/g

This works, but I'm looking for a way to do it in one line without an extra file.

enter image description here

I don't know how to debug the intermediate outputs of this process so I don't know what escaped characters are eaten at each step.

8
  • creating a variable rather than a file may work for the one line. You could try GIT_STATUS="$(var='s/"/\\\"/g' ; sed -f <(echo $var) <(shell git status -s))" Commented Feb 18, 2025 at 13:27
  • Please give an example of what your expected output is. It's not very clear (to me). Commented Feb 18, 2025 at 14:35
  • It looks like you are setting GIT_STATUS as a make variable, or maybe a shell variable. What does this have to do with C or the C preprocessor? Or with Eclipse? Commented Feb 18, 2025 at 14:47
  • @sseLtaH doesn't work. Produces empty string. Commented Feb 18, 2025 at 15:41
  • @pmacfarlane added expected output Commented Feb 18, 2025 at 15:42

1 Answer 1

2

sed accepts the backslash (\) as an escape character in regular expressions and in s-command replacement strings. You need to double it to represent a literal backslash, so if you want to replace " with \" then sed needs to see:

s/"/\\"/g

(Alternatively, the s/"/\\\"/g you report using in an external file is equivalent.)

Supposing that your $(shell ...) works as you seem to intend it to do*, your command will be evaluated by a shell, which, in a typical make-hosting environment, would be a Bourne-family shell. Such shells also accept the backslash as an escape character, except inside a single quotes. Also, you need the shell to treat the " characters as literals, not quote characters. So, the shell needs to see:

sed 's/"/\\"/g'

... or an equivalent.

make has idiosyncratic rules about escaping. The backslash is significant as an escape character only in a small number of narrow contexts, so you get a break here. (GNU) make needs to see:

$(shell sed 's/"/\\"/g')

That your starting command works indicates that Eclipse is not running make via a shell, so you don't need another level of escaping for the shell, but apparently Eclipse does perform its own escape processing. This is somewhat to be expected, because it definitely does (Eclipse) variable interpolation. That means it needs to provide a way to escape literal values that look like Eclipse variable references and literal values that look like escapes. I'm having trouble finding documentation of the details, but I'm fairly that means sure you need to double the backslashes again to escape them for Eclipse. That is, I think Eclipse needs to see:

$(shell sed 's/"/\\\\"/g')

Update: but apparently not. Eclipse is doing something strange and possibly buggy here.


*It's unclear to what extent you can or should rely on $(shell ...), because that's a GNU make feature, and tunneling it from Eclipse into make to be expanded there requires a combination of factors to align.

Sign up to request clarification or add additional context in comments.

2 Comments

I entered this in eclipse: GIT_STATUS="$(shell git status -s | sed 's/"/\\\\"/g')" and I got this in the generated .mk file in build folder: '-DGIT_STATUS="$(shell git status -s | sed '"'"'s/"/////"/g'"'"')"'
Ok, @elechris. At least the flipping of the backslashes to forward slashes looks like an Eclipse bug to me, but this is also where I refer you to the footnote in this answer, about requiring multuple factors to align. There might be a workaround, but if so then I'm not prepared to find it for you. I'm going to leave this answer up in case it helps someone else with that workaround, and because I think it has some value despite not getting you to your goal.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.