“设置-o noglob”在bash shell脚本(“set -o noglob” in bash

2019-07-31 07:03发布

我通常会写SQL在Bash shell脚本嵌入语句中被执行SQLPlus原样

#! /bin/sh

sqlplus user/pwd@dbname<<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/pwd@dbname

当执行这个问题上的变量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/pwd@dbname

有一些冲突或相当矛盾的描述setnoglob ,在互联网上。 所以我在寻找,如果有人可以解释这一点的小摆设。

Answer 1:

之后,有点挖我们的实现,使用设定-o noglob将完全解决这个问题

它并不解决问题这么多,因为它隐藏它。 眼下的问题是缺少引用的。 引用变量通常是一个很好的做法,因为它可以防止外壳从做意想不到的事情,当变量包含特殊字符,空格等。

禁用通配会阻止*被扩大,但是这通常不是你想要做的事。 它可以让你使用*? ,但如果你使用其他特殊字符的东西可能会断裂。

有许多的目录中的其他文件,我不知道为什么*选择执行somefile.sh或指向somefile.sh。

这里*扩展到所有在当前目录下的文件名,然后将此文件列表成为命令行。 外壳结束试图执行哪个文件名首字母顺序排列。


因此,要解决这个问题的正确方法是引用变量:

echo "$sqlvar" | sqlplus user/pwd@dbname

这将解决通配符问题。 另一个问题是,你所需要的\n转义序列被解释为一个换行符。 shell不会自动执行此操作。 要获取\n工作要么使用echo -e

echo -e "$sqlvar" | sqlplus user/pwd@dbname

或者使用字符串文本语法$'...' 。 这是单引号与前面一个美元符号。

sqlvar=$'insert into dummy1 select * from dummy2;\n commit;'
echo "$sqlvar" | sqlplus user/pwd@dbname

(或删除换行符。)



Answer 2:

我开始之前:@约翰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


文章来源: “set -o noglob” in bash shell script