如何在 bash 脚本中从命令行接受带空格的输入

如何在 bash 脚本中从命令行接受带空格的输入

目前我有一个 bash 脚本,其中我接受来自命令行的输入,但输入带有空格,并且 bash 脚本不读取空格后面的单词。脚本是这样的

#!/bin/bash
var1=$1
var2=$2
echo $var1
echo $var2

假设我将此文件保存为 test.sh。现在我的输入是这样的 -

./test.sh hi check1,hello world

输出是 -

hi
check1,hello

但我需要输出为

hi
check,hello world

PS:我无法提供双引号中的输入,所以我需要一些其他解决方案,可以用空格读取单词

答案1

那是不可能的。参数的单词拆分发生在脚本运行之前,因此当脚本启动时,参数已经被拆分为单词。阅读有关“分词”的内容,man bash了解更多详细信息。

如果你知道将有 2 个参数,第一个参数永远不会包含空格,您可以通过某种方式解决它

#! /bin/bash
first=$1
shift
rest="$*"

printf '<%s>\n' "$first" "$rest"

但它仍然会将多个空间缩小为一个。

答案2

正如 @choroba 正确指出的那样,你不能这样做,至少不能开箱即用。

原因是:shell 在执行任何操作之前,解析在命令行中,这是一个通过几个明确定义的步骤进行的过程。这些步骤之一是“字段分割”,其中 shell 将输入行分割成不同的部分。考虑:

命令 arg1 arg2

shell 必须以某种方式确定“command”是命令,“arg1”是第一个参数,“arg2”是第二个参数,不是吗?必须有一个原因为什么“arg1”是第一个参数而不是“arg1 arg2”,或者为什么“command”是命令而不是“command arg1”,等等。

不,话虽如此,有两件事会影响这种拆分的完成方式:(shell )变量 IFS 和 OFS。 IFS(“内部字段分隔符”)是一个字符列表,如果未屏蔽,它将分隔字段。在上面的示例中,“arg1”与“arg2”和“command”之间用空格分隔 - 这是 IFS 的一部分。

您可以自己将 IFS 设置为任何字符(甚至是空字符串),但默认情况下(POSIX 文档中规定)它设置为“空白”、“制表符”和“换行符”。欲了解更多信息,请参阅了解 IFS

在这个相当冗长的一般性介绍之后,这对您的问题意味着什么?

  1. 您可以通过操纵 IFS 来影响字段分割的完成方式,但您需要这样做您的脚本正在启动,即:

    % SAVIFS="$IFS" ;导出 IFS=""
     % /path/to/your/script arg1 arg2 ...
     % IFS="$SAVIFS"
  2. 您可以根据自己的规则在脚本内进行字段拆分。为此,您捕获全部将参数放入一个字符串中,然后自己将其拆分:

    /bin/bash #!/bin/bash
     chArgs =“$ *”
     arg1=“”
     arg1=“”
     [...]
     shopt -s 最后一管
     # 在这里分割$chArgs的内容,例如:
     回声“$chArgs”| IFS=''读取arg1 arg2
     printf "%s\n%s\n" "$arg1" "$arg2"
    
     # 或者,只是为了展示它是如何工作的:
     回声“$chArgs”| IFS=','读取arg1 arg2
     printf "%s\n%s\n" "$arg1" "$arg2"

但请注意,在处理字符串时,尤其是可能包含 IFS 中的字符的字符串时,您始终需要遵守正确的引用。在你的例子中:

#!/bin/bash
var1=$1
var2=$2
echo $var1
echo $var2

缺少这个正确的引用,我想这是它没有像您期望的那样工作的一个(额外的)原因。尝试:

#!/bin/bash
var1="$1"
var2="$2"
echo "$var1"
echo "$var2"

相关内容