我有 3 个文件:en.json
、en 1.json
和en 2.json
.它们都有以下内容
{
"ABC" : "/long_name",
"DFG" : "/{long_name}"
}
我运行下面的命令来替换ABC
为123
和DFG
456
grep -El 'ABC|DFG' *.json | xargs sed -ibak -e 's#ABC#123#g' -e 's#DFG#456#g'
文本被替换为en.json
but foren 1.json
并且en 2.json
失败并出现以下错误
sed: en: No such file or directory
由于某种原因,空格被忽略,我不确定如何在命令中处理它
答案1
您看到的问题是空格被视为分隔符。
一个简单的例子:
% echo a b | xargs ls
ls: cannot access a: No such file or directory
ls: cannot access b: No such file or directory
我们可以看到ls
尝试查找文件a
和b
.
相反,我们应该告诉xargs
和grep
使用不同的分隔符;最好的一个是 NUL 字符 (\0)。为此,您可以使用-Z
withgrep
和-0
with xargs
。
所以你的命令变成
grep -Z .... | xargs -0 ....
例如:
$ ls
en 1.json en 2.json en.json
$ grep -Z -El ABC *.json | xargs -0 sed -ibak -e 's/ABC/HHH/'
$ ls
en 1.json en 1.jsonbak en 2.json en 2.jsonbak en.json en.jsonbak
我们可以看到 3 个文件被修改(创建了“bak”文件)。
答案2
如果有疑问,请使用循环:
#!/usr/bin/env bash
while IFS= read -r file; do
sed -ibak -e 's#ABC#123#g' -e 's#DFG#456#g' "$file"
done < <(grep -El 'ABC|DFG' *.json)
上面假设您的文件名不包含换行符。
答案3
您可以使用 JSON 感知工具来jq
执行替换:
jq '."123" = ."ABC" | ."456" = ."DFG" | del(."ABC", ."DFG")'
输出
{
"123": "/long_name",
"456": "/{long_name}"
}
将此应用于所有三个文件,并记住引用包含空格的文件名,
for file in en.json 'en 1.json' 'en 2.json'
do
cp -p -- "$file" "$file.old"
jq '."123" = ."ABC" | ."456" = ."DFG" | del(."ABC", ."DFG")'<"$file.old" >"$file" &&
: rm -f -- "$file.old"
done
删除:
前面的rm
即可删除保存的原始文件。