Sed 变量太长

Sed variable too long

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

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

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

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

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

也许 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 本身来绕过环境变量 space 和参数长度的限制。

最稳妥的方法大概就是让Bash自己展开这个变量。您可以创建一个 Bash 脚本,其中包含 here documentmyFile.json 的全部内容,占位符 {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, ..."}