我正在编写一个名称帮助脚本来自动设置"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"
}