如何在bash脚本中采用参数“AS IS”?

seb*_*elk 0 bash

我有一个名为 readvar.sh 的脚本:

#! /bin/bash
a="$1"

echo "$a"
Run Code Online (Sandbox Code Playgroud)

我想在用户输入时从字面上获取参数,

例如,如果用户运行: ./readvar.sh \\

它应该输出\\而不需要用引号括起来的参数。

那可能吗?

ilk*_*chu 5

一般来说,你不能这样做。

如果您运行./readvar.sh \\,您编写命令的 shell 会解析命令行,将空格识别为单词分隔符,并将反斜杠识别为引用下一个字符(另一个反斜杠)。然后它以两个词./readvar.sh和 结束\,并启动程序./readvar.sh,将这两个词放入启动进程的参数列表中。(命令名称是参数 #0,它出现在argv[0]C 程序中。)

请注意,如果用户输入./readvar.sh '\'或bs='\'; ./readvar "$var"替代,或者使用类似于system("./readvar.sh", "\\");Perl 程序的内容启动脚本,您将获得类似的结果。脚本通常无法知道发生了什么。


您可以做的是以适合作为 shell 输入的格式打印所有参数,例如在 Bash 中使用

if [ "$#" -ne 0 ]; then
    printf "%q " "$@"
fi
echo 
Run Code Online (Sandbox Code Playgroud)

请注意,输出是这样的,它会在猛砸工作,但也许不是在一个标准的外壳,因为它使用了$'\n'引号的换行符等。此外,它会输出的形式\\,无论你用\\或'\'或"\\"启动脚本时。

同样在 Bash 中,您可能会extdebug为此滥用。这会将 Bash 的 DEBUG 陷阱看到的命令行安排在运行的命令的环境中:

export CMDLINE
trap 'CMDLINE=$BASH_COMMAND; true' DEBUG
shopt -s extdebug
Run Code Online (Sandbox Code Playgroud)

但请注意,那里的命令行没有展开,因此如果您运行env abc=$var |grep CMD,您将看到env abc=$var,而不是展开的值。

当然,如果您的命令不是从采取额外步骤的 Bash shell 启动的,这将不起作用。如果您在进程树的更高层有这样一个 shell,CMDLINE可以将其设置为用于启动较早命令的命令。


现在,虽然存在那些 hacky 解决方法,但对于脚本的用户来说,使用其他方法来实现脚本最终应该做的事情可能会更好也更不奇怪。