en.json
、、、en 1.json
3つのファイルがありますen 2.json
。いずれも以下の内容を含んでいます。
{
"ABC" : "/long_name",
"DFG" : "/{long_name}"
}
次のコマンドを実行してandABC
に置き換えました。123
DFG
456
grep -El 'ABC|DFG' *.json | xargs sed -ibak -e 's#ABC#123#g' -e 's#DFG#456#g'
テキストは次のエラーに置き換えられますがen.json
失敗en 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}"
}
これを3つのファイルすべてに適用し、スペースを含むファイル名を引用することを忘れないでください。
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
と、保存した元のファイルが削除されます。