5

I have a json string, which has a potpourri of doubly escaped/singly escaped newline chars. Json parser doesn't allow its string value to have single backslash escapes.

I need to uniformly make all of them to double escapes

Content looks like,

this newline must not be changed ---- \\n
this newline must be changed - \n

When i run sed command,

 sed -i 's/([^\])\n/\\n/g' ~/Desktop/sedTest 

it is not replacing anything

([^\]), this pattern is used to not change \n that already has one more backslash.

3 Answers 3

3

Given your sample input:

$ cat /tmp/foo
this newline must not be changed ---- \\n
this newline must be changed - \n

This seems to do what you want:

$ sed -e 's@\([^\]\)\\n@\1\\\\n@' /tmp/foo
this newline must not be changed ---- \\n
this newline must be changed - \\n
2
  • hi, why do we need \1 in the destination pattern?
    – user93868
    Commented Sep 14, 2015 at 14:16
  • Assume the input was: foo\n. The [^\] part capture part will match the second o in foo. The \1 is a group that contains that portion of the match. I include \1 so that you don't loose that character. Commented Sep 14, 2015 at 14:19
2

try

sed -i 's,\([^\\]\)\\n,\1\\\\n,'  file
sed -i 's,\([^\]\)\\n,\1\\\\n,'  file

where

  • \ must be escaped by \\\\
  • \( .. \) is the capture pattern
  • \1 on right hand is the first captured pattern.
  • second form with a single \ in [^\] as per @cuonglm suggestion.

You need to keep the pattern, or it will be discarded.

4
  • in simpler sed replaces like, sed 's,abc,def,, i never have to capture a pattern to make sure, that the pattern gets replaced.. in this case alone, why is \1 used to capture it?
    – user93868
    Commented Sep 14, 2015 at 14:20
  • in s/abc/dev/ , abc is discarded.
    – Archemar
    Commented Sep 14, 2015 at 14:20
  • makes sense....
    – user93868
    Commented Sep 14, 2015 at 14:24
  • The second backslash inside the square brackets is unnecessary. If you use -r for versions of sed that support it (or -E on OS X, et al) you can eliminate the backslashes before the parentheses. sed -ri 's,([^\])\\n,\1\\\\n,' Commented Sep 14, 2015 at 20:43
2

With \n in the LHS, you attempted to match a newline character instead of literal \n.

Try:

sed -e 's/\([^\]\)\(\\n\)/\1\\\2/g' file

or shorter with extended regular expression:

sed -E 's/([^\])(\\n)/\1\\\2/g' file
0

You must log in to answer this question.