![如何解决参数太长](https://linux22.com/image/162017/%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3%E5%8F%82%E6%95%B0%E5%A4%AA%E9%95%BF.png)
我是 shell 脚本新手。我正在修改现有的 shell 脚本,在其中我必须创建动态 html 内容并将该内容分配到变量中,并使用此变量值在 shell(Linux) 内的模板中进行替换。
我使用下面的代码片段,当 html 内容较少时,它工作正常,但如果内容很大,则同样会失败。如何解决这个问题。
encStr="$(cat ./dynamiccontent.html | base64)"
echo $encStr
awk -v var="$encStr" '{gsub("REPLACECONTENT", var, $0); print}' /path/tomytemplate > output.tmp
答案1
@mosvy 已经为您提供了一个很好的答案。
这个故事的简短寓意是:使用 shell 变量来存储未验证长度的数据不是一个好主意。一般来说,使用 shell 变量或 shell 根本不是一个好主意,因为它们是混乱的编程语言。但是,如果您绝对必须将内容存储在 shell 变量中,您也可以尝试这个疯狂的特技,逐步介绍:
通过进程替换创建包含所有内容的临时文件。事实是,shell 内置函数不受正常子进程参数限制的限制。
awk -v patternFile=<( printf "$encStr" )
使用 AWK 的繁琐方式(毕竟,这是一个典型的面向行的 Unix 工具),将整个临时文件读入 AWK 变量“内容”,首先将其拆分为行,然后使用字符串连接重建它,添加任何换行符被分裂移除。
awk -v substitutionFile=<( printf "$encStr" ) 'BEGIN {while ((getline line <substitutionFile) > 0) { contents = contents line "\n"}}'
然后,以您已经用来确定模板文件中要替换的标记的正常面向行的方式,执行替换:
awk -v substitutionFile=<( printf "$encStr" ) 'BEGIN {while ((getline line <substitutionFile) > 0) { substitutionString = substitutionString line "\n"}} {gsub("REPLACECONTENT", substitutionString, $0); print}' /path/tomytemplate > output.tmp
现在上面的解决方案很丑陋......但是按照 *nix shell 的标准,还不够丑陋!如果已经使用 *nix shell,为什么不直接使用heredoc呢?这样,您就可以减少 printf 命令被重新定义为函数(它在我的系统上,在生产代码中失败:D)的风险,但会引发文件包含heredoc分隔符的风险:
awk -v substitutionFile=<( cat <<HOPEFULLY_UNIQUE_HEREDOC_DELIMITER
$encStr
HOPEFULLY_UNIQUE_HEREDOC_DELIMITER
) 'BEGIN {while ((getline line <substitutionFile) > 0) { substitutionString = substitutionString line "\n"}} {gsub("REPLACECONTENT", substitutionString, $0); print}' /path/tomytemplate > output.tmp
请注意,定界文档中的变量替换算作引号,因此您不应使用 quote $encStr
,否则您的替换字符串也将包含引号!这是 shell 替换的第 1749203 条规则。在其他情况下,主要规则很简单:对变量和命令替换使用双引号,否则就会死。
在这种情况下,不是cat
内置的并不重要,因为它只会将其标准输入重定向到由heredoc创建的临时文件,而它本身没有长度限制,因为不涉及参数传递。