sed 模式将“替换为 \”和 \ 替换为 \\(json 字符串除外)

sed 模式将“替换为 \”和 \ 替换为 \\(json 字符串除外)

"我在替换to\"\to\\以及 except "json 时遇到问题

test.txt输入文件

"a"     "b"     
{"1":"female","2":"197312","3":"359","4":"201109","5":"mail"}
\uff08\u524d\u5bfe\u5fdc

我想输出像

\"a\"     \"b\"     
{"1":"female","2":"197312","3":"359","4":"201109","5":"mail"}
\\uff08\\u524d\\u5bfe\\u5fdc

答案1

为了更加健壮,您可以进行完整的 json 解析:

perl -0777 -pe '
  s@(".*?"|\\)|(\{(?:"(?:\\.|[^"])*+"|(?2)|[^"{}]++)*+\})|[^{}\\"]+@
  $1 ? $1 =~ s/["\\]/\\$&/gr : $&@gse'

哪个输入像

"a"     "b"     "c{d"
{"1":"female","2":"197312","3":"359","4":"201109","5":"mail"}
{
  "1": {"x": "y"}
  "2": "}}}"
  "3": ["{\"x", "}"]
}
\uff08\u524d\u5bfe\u5fdc

给出

\"a\"     \"b\"     \"c{d\"
{"1":"female","2":"197312","3":"359","4":"201109","5":"mail"}
{
  "1": {"x": "y"}
  "2": "}}}"
  "3": ["{\"x", "}"]
}
\\uff08\\u524d\\u5bfe\\u5fdc

您可能想澄清如果输入包含json 对象"foo\"bar""foo\nbar"在 json 对象之外您想要做什么。

答案2

在您展示的简单示例中,这很容易。只需转义不以 开头的行上的字符{

$ sed -E '/^[^{]/s|(["\])|\\\1|g' file 
\"a\"     \"b\"     
{"1":"female","2":"197312","3":"359","4":"201109","5":"mail"}
\\uff08\\u524d\\u5bfe\\u5fdc

然而,如果您的 JSON 可以跨越多行,事情就会变得更加复杂。对于这种情况,您可以编写一个小脚本来计算打开{和关闭的次数},并且仅在这些数字相等时应用替换(因此当我们不在 JSON 字符串中时)。就像是:

perl -F'' -ne 'for (@F){$op++ if /{/; $cl++ if /}/; if($cl==$op){s|["\\]|\\$&|g;}print}' file 

{然而,如果 JSON 字符串本身可以包含or}不表示 JSON 部分(例如{"1":"b-{c}"}或其他),这也会中断。对于这种情况,请使用斯蒂芬的方法反而。

答案3

$ sed 's/\(\\\|^"\|"$\|"[ \t]\)/\\\1/g' test.txt | sed 's/\([ \t]\)"/\1\\"/g'
  • \将or替换"为行首、行尾或空格/制表符之前:
    's/\(\\\|^"\|"$\|"[ \t]\)/\\\1/g'
  • "在空格/制表符之后:sed 's/\([ \t]\)"/\1\\"/g'

因此,只有当您的 json 字符串不包含任何空格/制表符并且位于一行时,这才有效。

相关内容