簡體   English   中英

bash腳本中變量的轉義

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

注意:

  • 在帶引號的heredoc(目錄cat <<'EOF' )內, 不會執行任何替換,因此不需要轉義 因此,我們可以完全按照我們希望其在生成的文件中存在的方式編寫代碼。
  • 生成代碼時,請使用printf %q對值進行轉義,以便求回到原始值。 否則,包含$(rm -rf ~)的變量可能會使給定命令運行(如果在文字單引號內將其替換,則使內容$(rm -rf ~)'$(rm -rf ~)'逃脫他們)。
  • Glob擴展返回結果列表; 存儲結果的適當數據類型是數組,而不是字符串。 因此, file=( gromacs* )使結果顯式存儲在數組中,下面的代碼將檢查是否有多個結果,以及結果是否是原始glob表達式(表示否)。已存在匹配項)。
  • 所有擴展都需要加引號,以防止字符串分割。 這意味着"$HOME"/* ,而不是$HOME/* -否則,每當用戶有一個包含空格的主目錄時,您都會遇到問題(是的,這確實會發生–考慮您擁有/Users/Firstname Lastname Windows派生平台/Users/Firstname Lastname ,或者您已在其中裝入主目錄卷的站點)。
  • 與用於編寫腳本的工具相反, pushdpopd是一個交互式擴展。 由於派生外部程序(例如cp )涉及fork()操作,並且在該子Shell發生作用時,該子Shell中的任何目錄更改都會終止,因此可以通過產生一個子Shell,在該子Shell中進行cd來避免對它們的任何需要,並且然后使用exec內置execcp替換子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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM