捕获逐字命令行(包括引号!)以调用脚本内部

时间:2014-05-27 15:45:29

标签: bash shell

我试图写一个"手机之家"脚本,它将确切的命令行(包括使用的任何单引号或双引号)记录到MySQL数据库中。作为后端,我有一个包装数据库的cgi脚本。脚本本身在cgi脚本上调用curl并包含各种参数作为参数,包括逐字命令行。

显然我在这里有很多报价逃避,而且我已经陷入了bash阶段。目前,我甚至无法通过bash逐字打印所提供的论据:

期望的输出:

$ ./caller.sh -f -hello -q "blah"
-f hello -q "blah"

使用echo:

caller.sh:

echo "$@"

给出:

$ ./caller.sh -f -hello -q "blah"
-f hello -q blah

(我还尝试了echo $@echo $*

使用printf%q:

caller.sh:

printf %q $@
printf "\n"

给出:

$ ./caller.sh -f hello -q "blah"
-fhello-qblah

(我也试过print %q "$@"

我不仅欢迎帮助解决我的bash问题,而且欢迎提供更多关于实施此问题的一般性建议"电话回家"更整洁!

4 个答案:

答案 0 :(得分:5)

没有办法编写caller.sh来区分在shell上调用的这两个命令:

./caller.sh -f -hello -q "blah"
./caller.sh -f -hello -q blah

完全相同。

如果要确保命令接收特殊字符,请用单引号括起参数:

./caller.sh -f -hello -q '"blah"'

或者,如果您只想将一个参数传递给caller.sh

./caller.sh '-f -hello -q "blah"'

答案 1 :(得分:2)

您可以从shell历史记录中获取此信息:

function myhack {
  line=$(history 1)
  line=${line#*  }
  echo "You wrote: $line"
}
alias myhack='myhack #'

哪种方法可以解释:

$ myhack --args="stuff" * {1..10}    $PATH
You wrote: myhack --args="stuff" * {1..10}    $PATH

然而,引用只是用户告诉shell如何构造程序的参数数组的方式。要求记录用户引用他们的参数的方式就像要求记录用户按键的次数以及他们当时佩戴的内容。

要记录一个明确捕获所有提供的参数的shell命令行,您不需要任何交互式shell hacks:

#!/bin/bash
line=$(printf "%q " "$@")
echo "What you wrote would have been indistinguishable from: $line"

答案 2 :(得分:1)

我知道您想要捕获调用者给出的参数。

首先,呼叫者使用的引号用于在呼叫解释期间进行保护。但他们作为论点存在。

一个例子:如果有人用一个参数调用你的脚本" Hello World!" Hello和World之间有两个空格。然后,您必须在脚本中保护始终 $ 1,以免丢失此信息。

如果要记录正确转义的所有参数(例如,在它们包含的情况下,例如连续的空格......),使用" $ @"双引号。 " $ @"相当于" $ 1" " $ 2#34; " $ 3#34; " $ 4#34;等

因此,要记录参数,我建议在调用者的开头使用以下内容:

i=0
for arg in "$@"; do
    echo "arg$i=$arg"
    let ++i
done

## Example of calls to the previous script
#caller.sh '1' "2" 3 "4 4" "5  5"
#arg1=1
#arg2=2
#arg3=3
#arg4=4 4
#arg5=5  5

答案 3 :(得分:0)

@Flimm是正确的,没有办法区分参数"foo"foo,只是因为在程序接收之前,shell 删除了引号。你需要的是"$@"(带引号)。