【问题标题】:Sed variable too longsed 变量太长
【发布时间】:2015-03-23 16:08:26
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 如果您能向我们提供您的输入和所需输出的简化的、有代表性的样本,那将会很有用。
  • 你想要在你的 json 文件中找到 {FILES} 的整个列表吗?
  • 问题已编辑,添加了示例,并且 {FILES} 是唯一的,因此整个列表替换了该字符串。
  • stackoverflow.com/questions/28865473/… 的答案对您有帮助吗?如果您可以在没有导出的情况下将您的 aws 命令放在同一个脚本中?

标签: bash sed


【解决方案1】:

最安全的方法可能是让 Bash 自己扩展变量。您可以创建一个包含here document 的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/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, ..."}

【讨论】:

  • 非常好的技巧。是否有另一种方法可以将 bash 作为子 shell 调用,这样就不需要将 $FILES 导出为 env 变量?
  • @Bastien974 只需将/bin/bash 替换为source /dev/stdin;查看我的编辑。
【解决方案2】:

也许 perl 的限制会更少?

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

【讨论】:

  • 试过了,同样的限制。
  • 我真的很惊讶。 Perl 和 sed 都有相当惊人的缓冲区限制(或​​缺乏)......
  • perl:参数列表太长
【解决方案3】:

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

显然,我会保留最后一行的注释,直到您确信它有效...

【讨论】:

  • 是的,它有效,如果没有更好的选择,我会使用它。
【解决方案4】:

也许只是不这样做?你能不能:

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

并从您的其他 json 文件中引用 myFile2.json? (如果这对您有用,您应该将全局 f 变量放入命名空间。)

【讨论】:

  • json 文件用于提供另一个命令:"aws cloudfront create-invalidation --distribution-id xxx --invalidation-batch "$(
【解决方案5】:

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

【讨论】:

    猜你喜欢
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多