我需要用一个包含数千条路径的bash变量替换json文件中的唯一字符串:{FILES}:$ {FILES}
sed -i "s|{FILES}|$FILES|" ./myFile.json
实现这一目标最优雅的方法是什么? $ {FILES}的内容是" aws s3"的结果。命令。内容如下:
FILES="/file1.ipk, /file2.ipk, /subfolder1/file3.ipk, /subfolder2/file4.ipk, ..."
我无法想到xargs会帮助我的解决方案。
答案 0 :(得分:2)
最安全的方法可能是让Bash自己扩展变量。您可以创建一个包含here document的完整内容为myFile.json
的Bash脚本,并将占位符{FILES}
替换为对变量$FILES
的引用(不是内容本身) 。执行此脚本将生成您寻找的输出。
例如,如果myFile.json
包含:
{foo: 1, bar: "{FILES}"}
然后脚本应该是:
#!/bin/bash
cat << EOF
{foo: 1, bar: "$FILES"}
EOF
您可以使用单个sed命令生成脚本:
sed -e '1i#!/bin/bash\ncat << EOF' -e 's/\$/\\$/g;s/{FILES}/$FILES/' -e '$aEOF' myFile.json
注意sed正在进行两次替换;第一个(s/\$/\\$/g
)以逃避JSON数据中可能出现的任何美元符号(将每$
替换为\$
)。第二个用{FILES}
替换$FILES
;文字文本$FILES
,不是变量的内容。
现在我们可以将所有内容组合成一个生成脚本的Bash单行程序,并通过将其传递给Bash立即执行它:
sed -e '1i#!/bin/bash\ncat << EOF' -e 's/\$/\\$/g;s/{FILES}/$FILES/' -e '$aEOF' myFile.json | /bin/bash
甚至更好,执行脚本而不生成子shell(如果设置$FILES
without export,则非常有用):
sed -e '1i#!/bin/bash\ncat << EOF' -e 's/\$/\\$/g;s/{FILES}/$FILES/' -e '$aEOF' myFile.json | source /dev/stdin
输出:
{foo: 1, bar: "/file1.ipk, /file2.ipk, /subfolder1/file3.ipk, /subfolder2/file4.ipk, ..."}
答案 1 :(得分:0)
也许perl会有更少的限制?
perl -pi -e "s#{FILES}#${FILES}#" ./myFile.json
答案 2 :(得分:0)
这有点严重,但你可以在shell内完成所有工作......
while read l
do
if ! echo "$l" | grep -q '{DATA}'
then
echo "$l"
else
echo "$l" | sed 's/{DATA}.*$//'
echo "$FILES"
echo "$l" | sed 's/^.*{DATA}//'
fi
done <./myfile.json >newfile.json
#mv newfile.json myfile.json
显然我会留下最后一行评论,直到你确信它有效为止......
答案 3 :(得分:0)
也许只是不做?你能说:
echo "var f = " > myFile2.json
echo $FILES >> myFile2.json
从你的其他json文件中引用myFile2.json? (如果这对您有用,则应将全局f变量放入命名空间。)
答案 4 :(得分:0)
不要将所有这些变量放在环境变量中,而是将它们放在一个文件中。然后在perl中读取该文件:
foo.pl:
open X, "$ARGV[0]" or die "couldn't open";
shift;
$foo = <X>;
while (<>) {
s/world/$foo/;
print;
}
要运行的命令:
aws s3 ... >/tmp/myfile.$$
perl foo.pl /tmp/myfile.$$ <myFile.json >newFile.json
希望通过拉动perl本身内的所有处理来绕过环境变量空间和参数长度的限制。