4

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.

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.

  • 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? – Madhavan Sep 14 '15 at 14:20
  • in s/abc/dev/ , abc is discarded. – Archemar Sep 14 '15 at 14:20
  • makes sense.... – Madhavan Sep 14 '15 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,' – Dennis Williamson Sep 14 '15 at 20:43
4

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
  • hi, why do we need \1 in the destination pattern? – Madhavan Sep 14 '15 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. – Andy Dalton Sep 14 '15 at 14:19
3

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

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.