Sed变量太长

  • 本文关键字:变量 Sed bash sed
  • 更新时间 :
  • 英文 :


我需要用包含数千条路径的bash变量替换json文件中的唯一字符串:{FILES}

sed -i "s|{FILES}|$FILES|" ./myFile.json

实现这一目标最优雅的方式是什么?${FILES}的内容是"aws s3"命令的结果。内容看起来像:

FILES="/file1.ipk, /file2.ipk, /subfolder1/file3.ipk, /subfolder2/file4.ipk, ..."

我想不出一个xargs可以帮助我的解决方案。

最安全的方法可能是让Bash自己扩展变量。您可以创建一个包含here文档的Bash脚本,其中包含myFile.json的全部内容,占位符{FILES}由对变量$FILES的引用(而不是内容本身)代替。执行此脚本将生成您所寻求的输出。

例如,如果myFile.json将包含:

{foo: 1, bar: "{FILES}"}

那么脚本应该是:

#!/bin/bash
cat << EOF
{foo: 1, bar: "$FILES"}
EOF

您可以使用一个sed命令生成脚本:

sed -e '1i#!/bin/bashncat << EOF' -e 's/$/\$/g;s/{FILES}/$FILES/' -e '$aEOF' myFile.json

注意sed正在进行两次替换;第一个(s/$/\$/g)逃脱JSON数据中可能出现的任何美元符号(用$替换每个$)。第二种是用CCD_ 9代替CCD_;文本$FILES而不是变量的内容。

现在,我们可以将所有内容组合到一个单独的Bash-one行中,该行生成脚本并通过管道将其发送到Bash:来立即执行它

sed -e '1i#!/bin/bashncat << EOF' -e 's/$/\$/g;s/{FILES}/$FILES/' -e '$aEOF' myFile.json | /bin/bash

或者更好的是,在不生成子shell的情况下执行脚本(如果$FILES设置为不导出,则非常有用):

sed -e '1i#!/bin/bashncat << 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, ..."}

也许perl会有更少的限制?

perl -pi -e "s#{FILES}#${FILES}#" ./myFile.json

这有点恶心,但您可以在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

很明显,我会留下最后一句话,直到你确信它有效。。。

也许就是不这么做?你能不能:

echo "var f = " > myFile2.json
echo $FILES >> myFile2.json

并从您的另一个json文件中引用myFile2.json?(如果适用的话,您应该将全局f变量放入命名空间中。)

与其将所有这些变量放在环境变量中,不如将它们放在文件中。然后在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本身中进行所有处理来绕过环境变量空间和参数长度的限制。

最新更新