如何在 bash 脚本中获取参数“AS IS”?

如何在 bash 脚本中获取参数“AS IS”?

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

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

echo "$a"

我想获取参数字面上地当用户输入时,

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

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

那可能吗?

答案1

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

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

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


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

if [ "$#" -ne 0 ]; then
    printf "%q " "$@"
fi
echo 

请注意,输出是这样的,它可以在 Bash 中工作,但可能不能在标准 shell 中工作,因为它使用$'\n'换行符等引号的形式。此外,\\无论您使用\\或启动脚本时,'\'它都会输出。"\\"

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

export CMDLINE
trap 'CMDLINE=$BASH_COMMAND; true' DEBUG
shopt -s extdebug

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

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


现在,虽然存在这些棘手的解决方法,但对于脚本的用户来说,使用其他方法来实现脚本最终应该做的事情可能会更好,也更不令人惊讶。

答案2

您可以read使用-r标志进行调用:

-r  Backslash does not act as an
    escape character.  The backslash
    is considered to be part of the line.
    In particular, a backslash-newline pair
    may not then be used as a line
    continuation.

所以:

IFS="" read -r a
echo "$a"

如果您输入“\”,将回显“\”。它还会保留空格(如果这不是目标,您可以删除 IFS 位)。

如果您只想将其作为参数传递,单引号应保持值不变。

./readvar.sh '\\'

读取var.sh:

#!/bin/bash

IFS="" read -r a
./usevar.sh "$a"

使用var.sh:

#!/bin/bash

echo "$1"

如果你输入\\readvar.sh就会usevar.sh回显\\

您需要 IFS 来保留文本开头和结尾的空格。

相关内容