"设置-o noglob"在bash shell脚本 [英] "set -o noglob" in bash shell script

查看:749
本文介绍了"设置-o noglob"在bash shell脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通常会写 SQL 语句内嵌在Bash shell脚本在 SQLPLUS 作为执行 -

 #! / bin / sh的sqlplus的用户名/密码@ DBNAME<< EOF
插入dummy1
选择dummy2 *;承诺;
出口;
EOF

这会工作得很好,并在执行时将行插入 dummy1 。我的一个同事来找我有一天用一个脚本像下面(简体)

 #! / bin / sh的
SQLVAR =插入dummy1选择dummy2 *;犯;
回声$ SQLVAR | sqlplus的用户名/密码@ DBNAME

这样做的问题是,当执行变量 SQLVAR 扩展 * 是在当前的所有文件目录,并最终将错误出像 -

  SQL>插入dummy1选择<  - 在当前目录下的所有文件名 - >
从dummy2;犯
                                                    *
ERROR位于第1行:
ORA-00923:FROM关键字未找到预期

我们的这一个首先的立场是壳层间preting * 在一个通配符上下文并列出所有的文件名,而shell变量扩展(不太知道为什么......?)。因此,为了了解这一点,我们不喜欢的东西如下 -

  $ VAR =你好*
$回声是$ var
你好< - 在当前目录下的所有文件名 - >

  $ *
KSH:somefile.sh:0403-006执行权限拒绝。 #since它没有执行权限

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

后,有点挖我们意识到,使用设置-o noglob 将完全解决这个问题,比如 -

 #! / bin / sh的
设置-o noglob
SQLVAR =插入dummy1从dummy2选择*; \\ n承诺;
回声$ SQLVAR | sqlplus的用户名/密码@ DBNAME

有一些冲突或相当矛盾说明设置 noglob ,在互联网上。所以我期待,如果有人可以解释这一点的小摆设。


解决方案

  

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


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

禁用通配做prevent的 * 被扩大,但是这通常不是你想要做的事。它可以让你使用 * ,但事情可能打破,如果你使用其他特殊字符。


  

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


下面 * 扩展到所有在当前目录下的文件名,然后将此文件列表成为命令行。外壳最终试图执行任何文件名首字母顺序排列。


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

 回声$ SQLVAR| sqlplus的用户/密码@ DBNAME

这将解决通配符问题。另一个问题是,你需要在 \\ n 转义序列是PTED作为一个新行间$ P $。外壳不会自动执行此操作。要获得 \\ n 工作要么使用回声-e

 回声-e$ SQLVAR| sqlplus的用户/密码@ DBNAME

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

  SQLVAR = $'插入dummy1从dummy2选择*; \\ n承诺;
回声$ SQLVAR| sqlplus的用户/密码@ DBNAME

(或删除换行符。)

I would usually write SQL statements inline in a Bash shell script to be executed in SQLPlus as-

#! /bin/sh

sqlplus user/pwd@dbname<<EOF
insert into dummy1 
select * from dummy2;

commit;
exit;
EOF

This would work just fine and will insert rows into dummy1 when executed. A colleague of mine came to me the other day with a script like below (simplified)

#! /bin/sh    
sqlvar="insert into dummy1 select * from dummy2;commit;"    
echo $sqlvar|sqlplus user/pwd@dbname

The issue with this is when executed the variable sqlvar expands the * to be all the files in the current directory and would eventually error out like-

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

Our first stance on this one was the shell was interpreting * in a wildcard context and listing all the file names while the shell variable expansion (not quite sure why....???). So, in order to understand this we did something like below-

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

But

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

There are a number of other files in the directory and I am not sure why * chose to execute somefile.sh or is pointed to somefile.sh.

After, a bit of digging we realized, using set -o noglob would resolve this issue entirely, like-

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

There are some conflicting or rather contradictory description of setting noglob, over the internet. So I am looking if someone could explain the knick knacks of this bit.

解决方案

After, a bit of digging we realized, using set -o noglob would resolve this issue entirely

It doesn't resolve the issue so much as it hides it. The issue at hand is the lack of quoting. Quoting variables is usually a good practice as it prevents the shell from doing unexpected things when the variable contains special characters, whitespace, etc.

Disabling globbing does prevent the * from being expanded, but that's generally not something you want to do. It'll let you use * and ?, but things could break if you used other special characters.

There are a number of other files in the directory and I am not sure why * chose to execute somefile.sh or is pointed to somefile.sh.

Here * expands to all of the file names in the current directory, and then this file list becomes the command line. The shell ends up trying to execute whichever file name is first alphabetically.


So, the right way to fix this is to quote the variable:

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

That will solve the wildcard problem. The other issue is that you need the \n escape sequence to be interpreted as a newline. The shell doesn't do this automatically. To get \n to work either use echo -e:

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

Or use the string literal syntax $'...'. That's single quotes with a dollar sign in front.

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

(Or delete the newline.)

这篇关于&QUOT;设置-o noglob&QUOT;在bash shell脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆