处理 sed 命令的文件名中的空格

处理 sed 命令的文件名中的空格

我有 3 个文件:en.jsonen 1.jsonen 2.json.它们都有以下内容

    {
      "ABC" : "/long_name",
      "DFG" : "/{long_name}"
    }

我运行下面的命令来替换ABC123DFG456

grep -El 'ABC|DFG' *.json | xargs  sed -ibak -e 's#ABC#123#g' -e 's#DFG#456#g'

文本被替换为en.jsonbut 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尝试查找文件ab.

相反,我们应该告诉xargsgrep使用不同的分隔符;最好的一个是 NUL 字符 (\0)。为此,您可以使用-Zwithgrep-0with 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即可删除保存的原始文件。

相关内容