[英]An escaping of the variable within bash script
我的bash脚本使用printf编写了另一个bash脚本。
printf "#!/bin/bash
HOME=${server}
file=gromacs*
file_name=\$(basename "\${file}")
date=\$(date +"\%m_\%d_\%Y")
for sim in \${HOME}/* ; do
if [[ -d \$sim ]]; then
simulation=$(basename "\$sim")
pushd \${sim}
cp \$file \${server}/\${results}/\${file_name}.\${simulation}.\${date}
echo "\${file_name}\ from\ \${simulation}\ has\ been\ collected!"
popd
fi
done" > ${output}/collecter.sh
这里的日期变量中的元素的转义有问题
date=\$(date +"\%m_\%d_\%Y")
以下部分无法正常工作的地方
"\%m_\%d_\%Y"
它导致由printf生成的新bash脚本不完整。
应该如何解决?
谢谢!
使用带引号的heredoc。
{
## print the header, and substitute our own value for HOME
printf '#!/bin/bash\nHOME=%q\n' "$server"
## EVERYTHING BELOW HERE UNTIL THE EOF IS LITERAL
cat <<'EOF'
file=( gromacs* )
(( ${#file[@]} == 1 )) && [[ -e $file ]] || {
echo "ERROR: Exactly one file starting with 'gromacs' should exist" >&2
exit 1
}
file_name=$(basename "${file}")
date=$(date +"%m_%d_%Y")
for sim in "$HOME"/* ; do
if [[ -d $sim ]]; then
simulation=$(basename "$sim")
(cd "${sim}" && exec cp "$file" "${server}/${results}/${file_name}.${simulation}.${date}")
echo "${file_name} from ${simulation} has been collected!"
fi
done
EOF
} >"${output}/collecter.sh"
注意:
cat <<'EOF'
)内, 不会执行任何替换,因此不需要转义 。 因此,我们可以完全按照我们希望其在生成的文件中存在的方式编写代码。 printf %q
对值进行转义,以便求回到原始值。 否则,包含$(rm -rf ~)
的变量可能会使给定命令运行(如果在文字单引号内将其替换,则使内容$(rm -rf ~)'$(rm -rf ~)'
逃脱他们)。 file=( gromacs* )
使结果显式存储在数组中,下面的代码将检查是否有多个结果,以及结果是否是原始glob表达式(表示否)。已存在匹配项)。 "$HOME"/*
,而不是$HOME/*
-否则,每当用户有一个包含空格的主目录时,您都会遇到问题(是的,这确实会发生–考虑您拥有/Users/Firstname Lastname
Windows派生平台/Users/Firstname Lastname
,或者您已在其中装入主目录卷的站点)。 pushd
和popd
是一个交互式扩展。 由于派生外部程序(例如cp
)涉及fork()操作,并且在该子Shell发生作用时,该子Shell中的任何目录更改都会终止,因此可以通过产生一个子Shell,在该子Shell中进行cd
来避免对它们的任何需要,并且然后使用exec
内置exec
用cp
替换子shell的PID,从而防止发生fork
,否则将允许cp
在与作为其父项的shell分开的进程中启动。 您必须使用esscaps在printf
中转义,例如:
date=\$(date +"%%m_%%d_%%Y")
应该打印date=\\$(date +"%m_%d_%Y")
。 但是您应该避免使用printf
,因为您没有使用它的功能。 相反,您可以将字符串指向文件:
cat > ${output}/collecter.sh <<'END'
HOME=${server}
...
done
END
这将使您避免许多转义,并使代码更具可读性。
尝试这个
date=\$(date +\"%%m_%%d_%%Y\")"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.