shell变量加单引号sql_关于shell:在Bash中的命令中扩展变量的单引号

我想从bash shell脚本中运行一个命令,该脚本在单引号和变量中包含单引号和一些其他命令。

如repo forall -c '....$variable'。

在这种格式中,对$进行转义,不展开变量。

我尝试了以下变体,但被拒绝:

repo forall -c '...."$variable" '

repo forall -c" '....$variable'"

" repo forall -c '....$variable'"

repo forall -c"'" ....$variable"'"

如果我用这个值代替变量,命令就可以执行了。

请告诉我哪里出错了。

repo forall -c ' ...before... '"$variable"' ...after...'

@N.M.回答

@注意,单引号是repo命令的一部分。我想这个不行

bash只接受单引号。要么您不在bash中,要么单引号不是repo命令的一部分。

我不确定能不能找到你,但是如果需要单引号的话,我就不会对所有的-c"……在……之前"进行回复了。$variable"…在……"工作之后?

它是一个在bash shell中运行的bash脚本,repo forall命令在单引号内接受参数。如果我替换实际值,命令运行正常。

@凯文。不,它给出错误:"before value after":"before value after"没有此类文件或目录。

从那以后我就一直在研究这个问题。我很幸运有回购协议。不过,我不清楚您是否需要在单引号之间强制使用命令。我研究了repo语法,我认为您不需要这样做。您可以在命令周围使用双引号,然后使用您需要的任何单引号和双引号,前提是您要转义双引号。如果你能为我提供真实的案例,我想我能提供更多的帮助。

顺便说一句,您可能从bash shell/脚本运行它,但是repo命令在sh shell中运行,根据文档:"-c:要执行的命令和参数。该命令通过/bin/sh和作为外壳位置参数传递后的任何参数进行计算。"

另一种可行的方法是将所需变量传递给repo执行,它似乎成功地将其传播到生成的sh上。例如:variable=$variable./repo forall-c'blahblah$variable blahblah'。包含完整命令的单引号由repo处理,实际计算$variable。

@凯文:是的,你是对的。所有回购都采用双引号,而不是单引号。我真蠢,一次也不检查。谢谢你的帮助。如果你把你的答案贴出来,我会接受它为正确答案。

@凯文:我也读过执行文件,我认为你是对的。但没时间检查。我要用双引号。非常感谢你!!!!

谢谢你,rachit:)

@rachit:是时候接受我的答案了;-)

参见:bash中单引号和双引号的区别。

更广泛地说,什么时候用引号括住shell变量?

在单引号内,所有的东西都是字面上保存的,毫无例外。

这意味着您必须关闭引号,插入一些内容,然后重新输入。

'before'"$variable"'after'

'before'"'"'after'

'before'\''after'

正如您可以验证的那样,以上每一行对于shell都是一个单独的单词。字符串连接只是通过并列完成的。引号(单引号或双引号,视情况而定)用于禁止解释各种特殊字符,如空格、$、;…有关引用的好教程,请参阅马克·里德的答案。同样相关:哪些字符需要在bash中转义?不要连接由shell解释的字符串

您应该绝对避免通过连接变量来构建shell命令。这是一个坏主意,类似于SQL片段的串联(SQL注入!).

通常可以在命令中包含占位符,并将命令与变量一起提供,以便被调用方可以从调用参数列表中接收它们。

例如,以下内容非常不安全。不要这样做

script="echo "Argument 1 is: $myvar""

/bin/sh -c"$script"

如果EDOCX1[2]的内容不可信,则存在以下漏洞:

myvar='foo"; echo"you were hacked'

不要使用上面的调用,而是使用位置参数。下面的调用更好——它是不可利用的:

script='echo"arg 1 is: $1"'

/bin/sh -c"$script" --"$myvar"

请注意,在分配给script时使用了单勾号,这意味着它是按字面意思进行的,没有变量扩展或任何其他形式的解释。

@乔,那就不行了。因为repo命令只接受参数,直到第一个引号结束。之后的任何操作都将被repo忽略并生成另一个错误。

@rachit-外壳不是这样工作的。"some"thing' like'this对shell来说都是一个单词。就解析而言,引号不会终止任何内容,而且shell调用的命令无法告诉引用内容的方式。

是的,乔。所以我现在明白了。谢谢你的帮助!

第二句话("你连单引号都逃不掉")使得单引号成为了外壳的黑洞。

@埃弗特:不知道怎么说得更好。我把句子删掉了。

@乔索,真丢脸:没有,笑话一落千丈。

repo命令不关心它得到什么样的报价。如果需要参数扩展,请使用双引号。如果这意味着你不得不反斜杠很多东西,使用单引号的大部分,然后打破它们,进入双打的部分,你需要扩展发生。

repo forall -c 'literal stuff goes here; '"stuff with $parameters here"' more literal stuff'

如果你感兴趣的话,解释如下。

从shell运行命令时,该命令作为参数接收的是以空结尾的字符串数组。这些字符串可以绝对包含任何非空字符。

但是,当shell从命令行构建字符串数组时,它会专门解释一些字符;这是为了使命令更容易(实际上是可能的)键入。例如,空格通常表示数组中字符串之间的边界;因此,单个参数有时称为"words"。但是一个论点可能仍然有空间;你只需要某种方式来告诉外壳你想要什么。

您可以在任何字符(包括空格或其他反斜杠)前面使用反斜杠来告诉shell从字面上处理该字符。但是当你可以这样做的时候:

echo \"Thank\ you.\ \ That\'ll\ be\ \$4.96,\ please,\"\ said\ the\ cashier

…会让人厌烦的。因此,壳牌公司提供了另一种选择:引号。这些有两个主要品种。

双引号称为"分组引号"。它们防止通配符和别名被扩展,但主要是用于在一个单词中包含空格。其他事情,如参数和命令扩展(由$发出信号的那种事情)仍然会发生。当然,如果您希望在双引号内使用文字双引号,则必须将其反斜杠:

echo"\"Thank you. That'll be \$4.96, please,\" said the cashier"

单引号更严厉。他们之间的一切都是完全按照字面意思,包括反斜杠。绝对没有办法在单引号中得到一个字面单引号。

幸运的是,外壳中的引号不是单词分隔符;它们本身不会终止单词。您可以在同一单词内输入和输出引号,包括不同类型的引号,以获得所需的结果:

echo '"Thank you. That'\''ll be $4.96, please," said the cashier'

这样做更容易——反斜杠更少,尽管右单引号、反斜杠文字单引号、左单引号序列需要一些适应。

现代shell添加了另一种POSIX标准中未指定的引用样式,其中前导单引号的前缀是美元符号。如此引用的字符串遵循类似于ANSI C编程语言中字符串文字的约定,因此有时称为"ansi字符串"和$'…'对"ansi引号"。在这样的字符串中,上面关于反斜杠的建议不再适用。相反,它们又变得特别了——不仅可以通过在其前面加上反斜杠来包含一个单引号或反斜杠,而且shell还扩展了ansi c字符转义(例如,换行符为,制表符为\t,十六进制代码为HH的字符为\xHH)。但是,否则,它们将表现为单引号字符串:不会发生参数或命令替换:

echo $'"Thank you.  That\'ll be $4.96, please," said the cashier'

需要注意的是,作为echo命令的参数接收的单个字符串在所有这些示例中都是完全相同的。在shell完成对命令行的分析之后,无法让正在运行的命令知道引用了什么。即使它想。

对。我现在明白了。它工作得很好。非常感谢你的帮助!

这个回答太棒了。

$'string'格式的posix是否兼容?还有,它有名字吗?

@通配符$'string'是一个非posix扩展,我将其称为"ansi字符串";我将这些事实合并到了答案中。这样的字符串可以在大多数与Bourne兼容的现代shell中使用:bash、dash、ksh(at&t和pd)和zsh都支持它们。

链接返回-在命令行参数中需要转义哪些字符?在Unix和Linux堆栈交换上。

编辑:(根据相关评论:)

从那以后我就一直在研究这个问题。我很幸运有回购协议。不过,我不清楚您是否需要在单引号之间强制使用命令。我研究了repo语法,我认为您不需要这样做。您可以在命令周围使用双引号,然后使用您需要的任何单引号和双引号,前提是您要转义双引号。

谢谢凯文的帮助。

下面是对我有用的-

QUOTE="'"

hive -e"alter table TBL_NAME set location $QUOTE$TBL_HDFS_DIR_PATH$QUOTE"

我希望tbl_hdfs_dir_path不是用户提供的输入btw,这将允许一个很好的SQL注入…

把QUOTE放在单独的变量中是完全多余的;双引号中的单引号只是一个普通字符。(另外,不要对私有变量使用大写。)

只使用PrimTf

而不是

repo forall -c '....$variable'

使用printf将变量标记替换为扩展变量。

例如:

template='.... %s'

repo forall -c $(printf"${template}""${variable}")

这是坏的;printf在这里并没有真正给你买任何东西,并且没有引用命令子脚本会导致新的引用问题。

变量可以包含单引号。

myvar=\'....$variable\'

repo forall -c $myvar

他们可以,但这不是正确的方法-你还是应该把"$myvar"放在双引号中。

这对你有用吗?

eval repo forall -c '....$variable'

是给你的吗?这个问题已经五岁了,已经有了一些答案,甚至一个公认的答案…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值