2012-09-01 62 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