Bash
從期望腳本中的變數中刪除輸入符 (r)
安裝 Ubuntu 16.04 期望腳本
在下面的簡單腳本中,目標是使用 ssh 在遠端電腦上的目錄中簡單地找到最舊的 .zip 文件。
然後使用 scp 將此文件下載到本地“workingBuild”目錄。
目前腳本
#!/usr/bin/expect set user "hidden" set pass "hidden" set sourceDir "/opt/tomcat/someDirectoryName/" set workingDir "/home/someUser/workingBuild" spawn sh -c "ssh $user@www ls -t $sourceDir | head -1" expect "password:" send "$pass\r" expect -re ".*\.zip" set sourceFile $expect_out(0,string) spawn sh -c "echo 'bob'$sourceFile'bob2'" spawn sh -c "scp $user@www:$sourceDir$sourceFile $workingDir" expect { password: {send "$pass\r"; exp_continue} }
問題
似乎我在儲存的文件名前面的 $sourceFile 變數中填充了一個隱藏的輸入符 (\r)。這反過來又導致 scp 命令出現問題,因為它將文件名和destinationDirectory 放在這樣的新行上。導致無效命令:
spawn sh -c scp meliudaj@www:/opt/tomcat/someDirectoryName/ build_0.0.1.zip /home/meliudaj/workingBuild
上面程式碼中的以下調試行也證明了這一點:
spawn sh -c "echo 'bob'$sourceFile'bob2'"
$sourceFile’bob2’ 總是在 ‘bob’ 下面的新行上
期望的結果是這樣的:
spawn sh -c scp meliudaj@www:/opt/tomcat/someDirectoryName/ build_0.0.1.zip /home/meliudaj/workingBuild
問題
我怎樣才能從 $ sourceFile variable, or how can I populate the $ sourceFile 變數以不同的方式防止 (\r) 首先出現。
PS 我已經嘗試了許多不同的嘗試來使用 sed、awk 和 tr 但我嘗試過的任何嘗試似乎都沒有幫助。
在您發送密碼並“按輸入”後,ssh 所做的第一件事就是發出一個換行符。您沒有在從 expect_out 緩衝區中提取的文本中考慮這一點。另請注意,expect 使用 CRNL 來表示換行符,我理解這是為了與一些網路協議標准保持一致。
這個互動式期望會話幾乎重現了這個問題。最後,我將變數的內容髮送到外部命令
od
以查看其中的確切內容:expect1.1> spawn sh -c {read password; ls -t | head -1} spawn sh -c read password; ls -t | head -1 42945 expect1.2> send "\r" expect1.3> expect "*.zip" somefile.zip expect1.4> set sourceFile $expect_out(0,string) somefile.zip expect1.5> exec od -c << $sourceFile 0000000 \r \n s o m e f i l e . z i p 0000016
您要做的是擷取以“.zip”結尾的文本,該文本出現在最後一個換行符之後。使用正則表達式相當簡單:
expect1.1> spawn sh -c {read password; ls -t | head -1} spawn sh -c read password; ls -t | head -1 42992 expect1.2> send "\r" expect1.3> expect -re {.*\r\n(.*\.zip)} somefile.zip expect1.4> set sourceFile $expect_out(1,string) somefile.zip expect1.5> exec od -c << $sourceFile 0000000 s o m e f i l e . z i p 0000014
請注意使用
(1,string)
來獲取第一組括號擷取的文本。