我需要从脚本内部生成脚本,但遇到问题,因为进入新脚本的一些命令正在被解释而不是写入新文件。 例如,我想创build一个名为start.sh的文件,我想设置一个variables到当前的IP地址:
echo "localip=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')" > /start.sh
写入文件的是:
localip=192.168.1.78
但是我想要的是新文件中的以下文本:
localip=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')"
以便在生成的脚本运行时确定IP。
我究竟做错了什么 ?
你让这不必要的困难。 使用引用sigil的heredoc传递文字内容,而不进行任何形式的扩展:
cat >/start.sh <<'EOF' localip=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/') EOF
使用<<'EOF'
或<<\EOF
,而不仅仅是<<'EOF'
是必不可少的。 后者将像原来的代码一样执行扩展。
如果你写给start.sh
东西需要基于当前变量,那么一定要使用printf %q
来安全地转义它们的内容。 例如,要设置您的当前$1
, $2
等在start.sh
执行过程中处于活动状态:
# open start.sh for output on FD 3 exec 3>/start.sh # build a shell-escaped version of your argument list printf -v argv_str '%q ' "$@" # add to the file we previously opened a command to set the current arguments to that list printf 'set -- %s\n' "$argv_str" >&3 # pass another variable through safely, just to be sure we demonstrate how: printf 'foo=%q\n' "$foo" >&3 # ...go ahead and add your other contents... cat >&3 <<'EOF' # ...put constant parts of start.sh here, which can use $1, $2, etc. EOF # close the file exec 3>&-
这比在所有需要追加的行上使用>>/start.sh
要高效得多:使用exec 3>file
然后>&3
只打开一次文件,而不是在每个生成输出的命令中打开一次。