尝试在MAC上使用sed编辑器交换JSON元素

时间:2019-06-13 22:22:49

标签: macos sed

我正在尝试创建一个脚本来查找JSON元素,并使用arg值对其进行更新。

 #!/bin/bash

# Shell script to verify the end to end D1 request flow
placeLocation=$1 
vehicleHeading=$2
message=$3
file=one.txt

sed -i '' '/location/c\   \"location\" : \"$placeLocation\",' $file
sed -i '' '/heading/c\   \"heading\" : \"$vehicleHeading\",' $file
sed -i '' '/message/c\   \"message\" : \"$message\",' $file

One.txt

"location":"<48.777098,9.181301> - 150.0m",
"message":"Hello there!",
"heading": "34",

但是出现以下错误

sed: 1: "/location/c\   \"locati ...": extra characters after \ at the end of c command
sed: 1: "/heading/c\   \"heading ...": extra characters after \ at the end of c command
sed: 1: "/message/c\   \"message ...": extra characters after \ at the end of c command
sed: 1: "file.txt": invalid command code f
sed: 1: "file.txt": invalid command code f
sed: 1: "file.txt": invalid command code f
sed: 1: "file.txt": invalid command code f

我刚刚开始学习sed编辑器,并尝试了多种方法,但无法弄清楚。任何帮助深表感谢!

2 个答案:

答案 0 :(得分:1)

请注意,您可能应该考虑使用jq之类的工具来编辑JSON文件。但是我认为您有充分的理由使用sed,所以那里有两个问题。

首先,您要在Mac OS X版本的sed上使用不具有这些功能的GNU sed功能。如果要在Mac OS X上使用GNU sed,请安装它:

▶ brew install gnu-sed

为GNU sed(以及其他有关引用字符串的Bash样式指南建议)修复代码:

cat > FILE <<EOF
"location":"<48.777098,9.181301> - 150.0m",
"message":"Hello there!",
"heading": "34",
EOF

placeLocation=myPlaceLocation
vehicleHeading=myVehicleHeading
message=myMessage

file=FILE

gsed -i -e '/location/c\' -e '"location": "'"$placeLocation"'",' "$file"
gsed -i -e '/heading/c\' -e '"heading": "'"$vehicleHeading"'",' "$file"
gsed -i -e '/message/c\' -e '"message": "'"$message"'",' "$file"

如GNU sed manual中所述,与-e命令在同一行上使用多个c\命令是GNU扩展。

如果要使用Mac OS X的sed,也许可以用这种方式编写:

sed -i '' '
  s/"location".*/"location": "'"$placeLocation"'",/
  s/"heading".*/"heading": "'"$vehicleHeading"'",/
  s/"message".*/"message": "'"$message"'",/
' "$file"

但是请注意,如果您需要代码对所有输入都具有鲁棒性,则必须清理输入。

答案 1 :(得分:1)

要可靠地执行此操作,您需要使用能够理解文字字符串(sed不能理解-参见Is it possible to escape regex metacharacters reliably with sed)的工具,例如awk:

$ awk 'BEGIN{FS=OFS=":"; val=ARGV[1]; ARGV[1]=""} $1=="\"message\""{sub(FS".*",FS); print $1, "\""val"\""}' 'what is 1/2?' one.txt
"message":"what is 1/2?"

$ awk 'BEGIN{FS=OFS=":"; val=ARGV[1]; ARGV[1]=""} $1=="\"message\""{sub(FS".*",FS); print $1, "\""val"\""}' 'what is 1&2?' one.txt
"message":"what is 1&2?"

$ awk 'BEGIN{FS=OFS=":"; val=ARGV[1]; ARGV[1]=""} $1=="\"message\""{sub(FS".*",FS); print $1, "\""val"\""}' 'what is \1?' one.txt
"message":"what is \1?"

以上内容将在每个UNIX盒上的任何shell中使用任何awk来可靠地运行。尝试在sed命令中将它们用作替换字符串。

执行所需操作的完整脚本将是:

#!/bin/env bash

# Shell script to verify the end to end D1 request flow
placeLocation=$1 
vehicleHeading=$2
message=$3
file=one.txt
tmp=$(mktemp)

awk '
    BEGIN {
        split("location heading message", tags)
        for (i in tags) {
            vals["\"" tags[i] "\""] = "\"" ARGV[i] "\""
            ARGV[i] = ""
        }
        FS=OFS=":"
    }
    $1 in vals {
        tag = $1
        sub(FS".*","")
        $0 = tag OFS vals[tag]
    }
1' "$placeLocation" "$vehicleHeading" "$message" "$file" > "$tmp" && mv "$tmp" "$file"