Shell-Script

當值中包含 $ 字元時如何為變數賦值

  • July 10, 2017

我的目標:將 scp 從一台伺服器自動傳輸到另一台伺服器,從使用者那裡獲取輸入提示時提供密碼,然後執行 scp。

這是我的程式碼

L_SRC_SID=source
L_SID=target
MOUNT_POINT=app07
SERVICE_PASS=some$value
APP_SERVER_1=hostname
SRC_MOUNT_POINT=app01

#And now transfer the file over
/usr/bin/expect -c "
  set timeout 1
  cd /$MOUNT_POINT/$L_SID/apps
  spawn scp -pr * apps@$APP_SERVER_1:/$SRC_MOUNT_POINT/$L_SRC_SID/apps .
  expect yes/no { send yes\r ; exp_continue }
  expect password: { send $SERVICE_PASS\r }
  expect 100%
  sleep 1
  exit
"

exit

挑戰: 1. 我無法分配一些 $ value value to variable SERVICE_PASS 2. How to make the expect send script work using such a variable that has $ 密碼中的字元。它因以下錯誤而失敗。

password: can't read "value": no such variable

任何幫助表示讚賞

我已根據建議更改了程式碼,但仍然出現相同的錯誤

L_SRC_SID=source
L_SID=target
MOUNT_POINT=app07
SERVICE_PASS='some$value'
APP_SERVER_1=hostname
SRC_MOUNT_POINT=app01

#And now transfer the file over
/usr/bin/expect -c "
  set timeout 1
  cd /$MOUNT_POINT/$L_SID/apps
  spawn scp -pr * apps@$APP_SERVER_1:/$SRC_MOUNT_POINT/$L_SRC_SID/apps .
  expect yes/no { send yes\r ; exp_continue }
  expect password: { send $SERVICE_PASS\r }
  expect 100%
  sleep 1
  exit
"

exit

這是完整的錯誤。

password: can't read "value": no such variable
   while executing
"send some$value\r "
   invoked from within
"expect password: { send some$value\r }"

因為您對expect 腳本主體使用雙引號,所以您必須同時處理shell變數擴展和expect(即Tcl)變數擴展。當expect 執行時,shell 變數已經被擴展,所以expect 看到這個:

expect password: { send some$value\r }

所以現在,您需要處理 Tcl 變數。

可以添加更多引用:

/usr/bin/expect -c "
   ...
   expect password: { send {$SERVICE_PASS}; send \r }

但這不是必需的:我會將期望腳本放在單引號中,並通過環境傳遞 shell 參數。這樣,每個變數只會被替換一次:無論是在 shell 中還是在 expect 中,您都不會感到意外。

export L_SRC_SID L_SID MOUNT_POINT SERVICE_PASS APP_SERVER_1 SRC_MOUNT_POINT

/usr/bin/expect -c '  # <- single quote
   set timeout -1
   cd /$env(MOUNT_POINT)/$env(L_SID)/apps
   spawn scp -pr * apps@$env(APP_SERVER_1):/$env(SRC_MOUNT_POINT)/$env(L_SRC_SID)/apps .
   expect {
       yes/no    { send yes\r ; exp_continue }
       password: { send $env(SERVICE_PASS)\r }
   }
   expect eof
'

一般來說,使用sleepin expect 意味著您要麼有錯誤的超時時間,要麼您期待錯誤的事情。我都改了。

對於這種情況,您需要將值括在單引號中:

'some$value'

雙引號會""抑製文件名擴展,但不會抑制變數擴展。

$ value="some$value"
$ echo $value
some

單引號''抑製文件名和變數擴展。

$ value='some$value'
$ echo $value
some$value

反引號````允許可變擴展

$ value=`some$value`
$ echo $value`

$

因此,要抑制諸如$, !,等字元的擴展",並/ 使用單引號!

引用自:https://unix.stackexchange.com/questions/377526