Linux 在GETOPTS中解析带引号的字符串

Linux 在GETOPTS中解析带引号的字符串,linux,bash,shell,scripting,Linux,Bash,Shell,Scripting,在解析选项时,我尝试接受以空格分隔的字符串来代替$OPTARG 比如说 /script-k'12 ad'ias' 如图所示,第三个字符串可以包含任何特殊字符。当我想解析整个字符串并处理一些选项时,有没有一种方法可以忽略中间的引号 已尝试插入\字符,但这不适用于我的大小写,因为我无法在字符串中插入任何字符 while getopts "a:k:" option do echo "${option}" case ${option} in a) functio

在解析选项时,我尝试接受以空格分隔的字符串来代替$OPTARG

比如说

/script-k'12 ad'ias'
如图所示,第三个字符串可以包含任何特殊字符。当我想解析整个字符串并处理一些选项时,有没有一种方法可以忽略中间的引号

已尝试插入\字符,但这不适用于我的大小写,因为我无法在字符串中插入任何字符


while getopts "a:k:" option
do
   echo "${option}"
   case ${option} in
     a)
        function_a ${OPTARG}   # <-- no quotes
      ;;
     k)
        function_k "${OPTARG}" # <-- quotes
      ;;
   esac
done

而getopts“a:k:”选项
做
回显“${option}”
中的案例${option}
(a)

函数${OPTARG}#我不确定我是否完全理解困难是什么;处理带有特殊字符的字符串有点棘手,但(NUL字符除外)基本上是可行的。需要注意的主要事项是:

  • 当您表示字符串文字时(在脚本中,或向脚本传递参数时),必须使用该字符串的有效shell表示,而不仅仅是原始字符串。例如,假设要传递/使用此字符串:

    12 34 kla#42@!' 2 M$" rtqas;::#
    
    在shell脚本或命令行中有多种表示此字符串的方法。您可以不加引号,但可以转义单个特殊字符,如下所示:

    12\ 34\ kla\#42@\!\'\ 2\ M\$\"\ rtqas\;::\#
    
    或者您可以将其用双引号括起来,并仅转义那些在双引号中保留特殊含义的字符(即双引号、反引号和美元符号,如果是bash交互式shell感叹号):

    如果它不包含单引号,您可以单引号;既然这样,你就不能用那种方法。但您可以混合使用方法,例如,在不包含单引号的部分周围使用单引号,并对单引号进行转义或双引号:

    '12 34 kla#42@!'\'' 2 M$" rtqas;::#'    # Single-quote is escaped
    '12 34 kla#42@!'"'"' 2 M$" rtqas;::#'   # Single-quote is double-quoted
    
    在bash中(但不是其他一些shell),还有ANSI-C转义字符串,用
    $”编写

    $'12 34 kla#42@!\' 2 M$" rtqas;::#'    # Single-quote is the only character that needs escaping
    
    请注意,以上所有内容只是表示完全相同字符串的不同方式;一旦shell解析了它,它们中的任何一个都会得到相同的结果。您可以使用任何方便的方法,但必须使用字符串的语法有效表示形式

  • 字符串存储在参数/变量中后,必须在该变量的引用周围加双引号。在大多数shell上下文中,当使用变量时不带引号,shell会将其拆分为单词(基于空格或
    IFS
    中的任何内容),并尝试展开任何看起来像文件通配符的内容;你不会想要这个的。但是如果它在双引号中,变量会被扩展,并且不会进行进一步的解析,它只是被无扰地传递

    事实上,在shell脚本中,即使不希望变量引用包含特殊字符,也应该始终使用双引号引用变量引用。我们在这里看到很多shell问题的答案是“如果你双重引用变量引用,你就不会有这个问题”

以下是一个基于脚本的示例:

#!/bin/bash

printopt() {
   printf '%s value is: <<%s>>\n' "$1" "$2"    # Double-quotes required here
}

while getopts "a:k:" option
do
   case "${option}" in    # This is one of the few places it's safe to leave off double-quotes. But they don't hurt.
     a)
        printopt "-a" "${OPTARG}"    # Double-quotes required here
      ;;
     k)
        printopt "-k" "${OPTARG}"    # Double-quotes required here
      ;;
   esac
done
#/bin/bash
printopt(){
printf“%s”的值是:\n'$1'$2'#此处需要双引号
}
而getopts“a:k:”选项
做
#中的案例“${option}”,这是为数不多的几个可以安全地省去双引号的地方之一。但是他们不疼。
(a)
printopt“-a”“${OPTARG}”#此处需要双引号
;;
(k)
printopt“-k”“${OPTARG}”#此处需要双引号
;;
以撒
完成
并使用各种字符串表示形式运行它:

$ ./argtest.sh -a 12\ 34\ kla\#42@\!\'\ 2\ M\$\"\ rtqas\;::\# -k "1 2 ad'ias"
-a value is: <<12 34 kla#42@!' 2 M$" rtqas;::#>>
-k value is: <<1 2 ad'ias>>
$ ./argtest.sh -a '12 34 kla#42@!'"'"' 2 M$" rtqas;::#' -k $'1 2 ad\'ias'
-a value is: <<12 34 kla#42@!' 2 M$" rtqas;::#>>
-k value is: <<1 2 ad'ias>>
$。/argtest.sh-a 12\34\kla\\ 42@!\'2\M\$\“\rtqas\:\ \ \35;-k“12个广告”
-值为:>
$./argtest.sh-a'1234kla#42@!“'2m$”rtqas;:#”-k$'12 ad'ias'
-值为:>
好吧,好吧,有一些情况比这更复杂:

  • 在某些情况下,字符串将在shell解析过程中多次运行,例如,当它在
    ssh
    上运行时(该命令由本地shell处理,传递到远程计算机,然后由该shell处理并执行),或者用作shell
    别名
    (解析
    alias
    命令,存储结果,然后在使用它时再次解析)。在这些情况下,您基本上需要两层(或可能更多)的引用/转义:获取原始字符串,通过上述任何方法引用/转义,然后获取该字符串和引用/转义(可能通过不同的方法)

  • 一些版本的
    echo
    将解析字符串中的转义(反斜杠)序列(使用与shell本身不同的规则),这可能会导致混淆。我建议在可能出现问题时使用
    printf
    ;唯一的问题是它比
    echo
    更复杂:它不仅打印参数,它使用的第一个参数是一个格式字符串,它控制其余参数的打印方式。请参阅上面脚本中的示例

  • 如果您将字符串传递给另一个脚本,而该脚本的参数和变量引用周围不使用双引号,那么您就注定要失败。在这种情况下,唯一可以做的就是修复另一个脚本


我不确定自己是否完全理解困难所在;处理带有特殊字符的字符串有点棘手,但(NUL字符除外)基本上是可行的。需要注意的主要事项是:

  • 当您表示字符串文字(在脚本中或向脚本传递参数时),必须使用该字符串的有效shell表示形式,而不仅仅是原始字符串。例如,假设您要传递/使用此字符串:

    12 34 kla#42@!' 2 M$" rtqas;::#
    
    在shell脚本或命令行中,有多种表示此字符串的方法。您可以将其保留为不带引号,但对单个特殊字符进行转义,如下所示:

    12\ 34\ kla\#42@\!\'\ 2\ M\$\"\ rtqas\;::\#
    
    或者可以用双引号将其括起来,并仅转义那些在双引号中保留特殊含义的字符(即双引号、反引号和美元符号,如果