查看一个 bash 脚本,该脚本从 Git 提交注释中获取输入来更新自身。简化:
script
:
#!/bin/bash
comment=''
printf '%s\n' "$comment"
upgrade_script() {
# Download latest:
curl -o updated_script https://path/to/file
# Get comment:
new_comment="$(curl https://path/to/comment)"
# Update comment='' with new_comment:
sed -i "3,0 s/comment=''/comment='$new_comment'/" updated_script
}
问题是注释是否包含中断sed
或mangles
重击的字符。例如:
# that's all she wrote! => comment='that's all she wrote!
# use /need/ over /want/ => s/comment=''/'use /need/ over /want'/'
当然,还有潜在的恶意但也有意想不到的事情,例如:
# Remove tmp files by: ' rm -r *;' => comment='Remove tmp files by: ' rm -r *;''
这足以解决这个问题吗?
在命令之前添加以下内容sed -i
:
new_comment=$(
sed \
-e "s/'/'\"'\"'/g" \
-e 's/[&\\/]/\\&/g; s/$/\\/; $s/\\$//'<<< "$new_comment"
)
对于bash
:
- 替换
'
为'"'"'
.
对于sed
:
- 转义符
&
、\
、/
和行终止符。
或者会出现什么故障?
理想情况下,根本不会这样做,但好奇地想知道。
旁注:
另一种解决方案是将其保存在一个文件中,可能是exit
在脚本中添加 并在其后添加文本,然后使用sed
或类似的方法来打印它。但这不是我的问题。
#!/bin/bash
code
code
code
# When in need of the comment:
sed -n '/^exit # EOF Script$/$ {/start_xyz/,/end_xyz/ ...}'
# or what ever. Could even record offset and byte-length safely
code
code
exit # EOF Script
start_xyz
Blah blah blah
blaah
end_xyz
想到这一点,我猜想:
comment=<<<'SOF'
...
SOF
只需更换任何一个即可SOF
避免过早结束。我的问题仍然是上面的消毒。谢谢。
看来你需要结合:
所以:
虽然 zsh+perl 比 bash+sed 是更好的选择:
请记住,
comment
最终可能包含一个 NUL 字符,这对于 zsh 及其内置函数或函数来说很好,但不能作为参数传递给外部命令。bash
删除$(...)
NUL。curl
要消除该风险,您可以通过管道将to的输出手动删除 NULtr -d '\0'
或 with或者如果有这样的角色就退出: