2013-01-31 60 views
1

我正在使用Mac OS X的pbpaste命令,該命令返回剪貼板的內容。我想創建一個shell腳本來執行pbpaste作爲單獨的bash命令返回的每一行。例如,讓我們說,剪貼板的內容包括以下文本行:如何在剪貼板上以bash命令的形式執行文本行

echo 1234 >~/a.txt 
echo 5678 >~/b.txt 

我想執行的每個這些行的shell腳本,創建兩個文件a.txt中和b.txt我家庭文件夾。相當數量的搜索和反覆試驗後,我已經得到了在那裏我能夠文本的各行分配給一個變量在while循環與下面的結構點:

pbpaste | egrep -o [^$]+ | while read l; do echo $l; done 

它發送下面到標準輸出,符合市場預期:

echo 1234 >~/a.txt 
echo 5678 >~/b.txt 

而不是簡單地呼應文本的每一行,然後我嘗試用下面的結構來執行它們:

pbpaste | egrep -o [^$]+ | while read l; do $l; done 

我認爲這會執行每一行(從而在我的home文件夾中創建兩個文本文件a.txt和b.txt)。相反,第一項(echo)似乎被解釋爲命令,其餘項(nnnn >~/...)似乎被集中在一起,就好像它們是單個參數一樣,導致以下內容被髮送到標準輸出而沒有創建任何文件:

1234 >~/a.txt 
5678 >~/b.txt 

我會在理解爲什麼我的構造不工作,什麼樣的變化可能得到它的工作的幫助表示感謝。

回答

2

[…]剩餘的術語(nnnn >~/...)看起來好像它們是單個參數,獲得混在一起的[hellip;]

不完全。該行實際上被分割爲空格(或任何$IFS指定的內容),但問題是不能從shell變量中獲取重定向運算符>。例如,這個片段:

gt='>' 
echo $gt foo.txt 

將打印> foo.txt,而不是打印換行符foo.txt

而且你會遇到類似的問題與其他各種shell元字符,如引號。

你需要的是eval內置的,這需要一個字符串,解析它作爲一個shell命令,並運行它:

pbpaste | egrep -o [^$]+ | while IFS= read -r LINE; do eval "$LINE"; done 

(該IFS=-r和周圍$LINE雙引號都以除了eval執行的處理外,還可以防止其他任何處理,以便保留引號內的空白。)

另一種可能性,這取決於你所需要的細節,簡直是管的命令到新的Bash實例:

pbpaste | egrep -o [^$]+ | bash 

編輯補充:對於這個問題,我發現你可以在一批中將所有內容都傳遞給eval;正如你可以(根據你的評論)寫pbpaste | bash,你也可以寫eval "$(pbpaste)"。這將支持多行while -loop等等,同時仍在當前shell中運行(如果希望它能夠引用shell參數,設置環境變量等,那麼它很有用)。

+0

對於實際適當使用'eval'的+1。另外,請注意,pipe-to-bash選項將允許使用多行結構(例如if和while語句的正常格式),但是逐行選項不會。 –

+0

哇,瑞克,謝謝你的美麗解釋和解決方案!在你和Gordon的帶領下,我繼續玩弄管道到打擊選項,發現我可以完全消除「egrep」和「while」。以下高效構造可以完美地處理相當複雜的多行代碼('while while循環,條件測試,變量增量...):'pbpaste | bash'。 – scolfax

+0

@scolfax:不客氣! – ruakh