[英]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.