动态转义变量

动态转义变量

我正在编写一个名称帮助脚本来自动设置"name":package.json 文件中的字段,以便它与某个正则表达式结构匹配,但我在实际设置名称时遇到了一些问题。它必须匹配的正则表达式是'\@abc\/([a-z]+-{0,1})+[a-z]*$'.

现在我基本上这样做(以及一些额外的东西来真正断言遵循命名约定):

pattern='\@abc\/([a-z]+-{0,1})+[a-z]*$'
if [[ ! $name =~ $pattern ]]; then 
  read -rp "New name: " newName
  sed -ri "s/(\s.\"name\"\:\s\").*/\1$newName\",/g" $1/package.json
fi

正如您可能看到的,这里的问题是变量$newName在 sed 中作为命令进行处理,它需要转义字符(假设用户实际上以正确的结构写入了新名称)。有没有办法做到这一点?最好尽可能地不依赖依赖。

答案1

从表面上看,这个问题是重复的如何确保插入到“sed”替换中的字符串转义所有元字符。然而,JSONsed是一种面向行的文本操作工具,而JSON是一种不面向行的结构化文档格式。因此,最好解决sed问题的“想要使用 JSON 文档”方面,而不是“我想以特定方式使用”方面。


由于这与 JSON 有关,因此最好使用支持 JSON 的工具,例如jq.

jq --arg newname '@abc/corrected-name' \
    'select( .name | test("^@abc/([a-z]-?)+[a-z]*$") | not ).name |= $newname' file.json

此命令假定输入由具有顶级name密钥的 JSON 文档组成。它(可能)修改输入文档并将结果写入标准输出。

简而言之,该jq表达式选择输入集中具有顶级name键的所有元素,其值不是匹配^@abc/([a-z]-?)+[a-z]*$。一旦选择了一个元素,它的name键值就会更新为 中的值$newvalue

这样做的好处是不需要将 shell 变量注入到表达式中,并且赋予内部$newname变量的值将自动进行 JSON 编码jq(如果需要以任何特定方式进行编码)。

输入文档如

{
  "name": "@abc/abc-foo"
}

该命令将保持不变,而

{
  "name": "bumblebee"
}

会变成

{
  "name": "@abc/corrected-name"
}

相关内容