2012-09-01 95 views
1

我通常會寫SQL語句內嵌在Bash shell腳本SQLPlus要執行原樣「設置-o noglob」在bash shell腳本

#! /bin/sh 

sqlplus user/[email protected]<<EOF 
insert into dummy1 
select * from dummy2; 

commit; 
exit; 
EOF 

這會工作得很好,並插入幾行dummy1執行時。我的一個同事來找我一天用一個腳本像下面(簡化)

#! /bin/sh  
sqlvar="insert into dummy1 select * from dummy2;commit;"  
echo $sqlvar|sqlplus user/[email protected] 

與此問題是,當執行變量sqlvar擴展*是在當前目錄下的所有文件,並最終錯誤出喜歡 -

SQL> insert into dummy1 select <--all the file names in the current directory--> 
from dummy2;commit 
                * 
ERROR at line 1: 
ORA-00923: FROM keyword not found where expected 

我們就這一個被殼正在演繹一個通配符背景*並列出所有的文件名,而shell變量擴展(不明白爲什麼....第一立足??? )。因此,爲了理解這一點,我們不喜歡的東西如下─

$ var="hello *" 
$ echo $var 
hello <--all the file names in the current directory--> 

$* 
ksh: somefile.sh: 0403-006 Execute permission denied. #since it had no execute permission 

有一些目錄中的其他文件,我不知道爲什麼*選擇執行somefile.sh或指向somefile.sh

後,有點挖我們意識到,使用set -o noglob將完全解決這個問題,喜歡 -

#! /bin/sh 
set -o noglob 
sqlvar="insert into dummy1 select * from dummy2;\n commit;"  
echo $sqlvar|sqlplus user/[email protected] 

setnoglob的一些衝突或相當矛盾的描述,在互聯網上。所以我在尋找是否有人能夠解釋這一點的小訣竅。

回答

6

後,有點挖我們的實現,使用設定-o noglob會解決這個問題完全

它不解決問題這麼多,因爲它隱藏它。手頭的問題是缺乏引用。引用變量通常是一種很好的做法,因爲它可以防止shell在變量中包含特殊字符,空格等時發生意外事件。

禁用globbing確實會阻止*被擴展,但這通常不是您想要做的事。它會讓你使用*?,但如果你使用其他特殊字符,事情可能會中斷。

該目錄中還有一些其他文件,我不知道爲什麼*選擇執行somefile.sh或指向somefile.sh。

這裏*展開到當前目錄中的所有文件名,然後這個文件列表成爲命令行。 shell最終會嘗試執行哪個文件名是按字母順序排列的。


因此,要解決這個問題的正確方法是引用變量:

echo "$sqlvar" | sqlplus user/[email protected] 

,將解決通配符問題。另一個問題是您需要將\n轉義序列解釋爲換行符。 shell不會自動執行此操作。爲了得到\n工作要麼使用echo -e

echo -e "$sqlvar" | sqlplus user/[email protected] 

或者使用字符串文本語法$'...'。這是前面帶有美元符號的單引號。

sqlvar=$'insert into dummy1 select * from dummy2;\n commit;' 
echo "$sqlvar" | sqlplus user/[email protected] 

(或刪除換行符。)

+0

感謝,但我們正在尋找設置'noglob'的意義(這顯然也解決了問題)。新的字符不會在那裏,我的錯誤修復了這個問題。 – Annjawn

3

在我開始:@約翰Kugelman的答案(適當引用)是解決這一問題的正確方法。設置noglob只能解決問題的一些變體,並在此過程中產生其他潛在問題。但是,既然你問了什麼set -o noglob做什麼,這裏是從ksh手冊頁的相關摘錄(順便說一下,你的標籤說bash,但錯誤消息說ksh。我假定你實際上使用ksh)。

noglob  Same as -f.

-f      Disables file name generation.

File Name Generation. 
    Following splitting, each field is scanned for the characters *, ?, (, 
    and [ unless the -f option has been set. If one of these characters 
    appears, then the word is regarded as a pattern. Each file name compo- 
    nent that contains any pattern character is replaced with a lexico- 
    graphically sorted set of names that matches the pattern from that 
    directory. 

那麼,是什麼意思呢?下面是一個簡單的例子,應該顯示效果:

$ echo * 
file1 file2 file3 file4 
$ ls * 
file1 file2 file3 file4 
$ * # Note that this is equivalent to typing "file1 file2 file3 file4" as a command -- file1 is treated as the command (which doesn't exist), the rest as arguments to it 
ksh: file1: not found 

現在看有noglob一套什麼樣的變化:

$ set -o noglob 
$ echo * 
* 
$ ls * 
ls: *: No such file or directory 
$ * 
ksh: *: not found