【问题标题】:Counting Whitespace in Arguments in KSH?在 KSH 的参数中计算空格?
【发布时间】:2011-01-28 06:09:54
【问题描述】:

我试图允许将其中包含空格的字符串计为整个字符串,而不是被解析。这就是我希望发生的事情:

$ ksh program.ksh "what up"
File 'what up' not found.

这就是我得到的:

$ ksh program.ksh "what up"
File 'what' not found.
File 'up' not found.

这是我尝试过的代码:

wflag=false
cflag=false

while getopts "cw" opt; do
  case "$opt" in
    c)
      cflag=true
      ;;
    w)
      wflag=true
      ;;
    /?)
      ;;
  esac
done

问题在于 1) 我尝试上面的 ksh program.ksh "what up" 之类的东西,以及 2) 当我尝试 ksh program.ksh "-w -c" 之类的东西时。第二个最令人困惑,因为当我打印出wflagcflag 时,它们都是正确的。 "-w -c" 不应该在这里被视为字符串吗?似乎内核(是内核在这里工作吗?)正在解析这个,尽管这正是我不想要的;我希望它被视为带有空格的字符串。我已经阅读了WordSplitting 和((关于论点的文章,但我不让我发布它)),认为我理解。显然我一定是遗漏了什么,或者根本没有真正理解它:P

我的直觉告诉我getopts 发生了一些事情,它会自动消除任何空白。我尝试过$(opt) 而不是"$opt",以及大括号和/或单引号(我很确定单引号不会起作用)。唉,没有雪茄。

任何帮助将不胜感激,并感谢您阅读这堵文字墙。

【问题讨论】:

    标签: unix ksh


    【解决方案1】:

    case 语句中的最后一项应该有一个反斜杠而不是斜杠。让我们进行一些其他更改以进行诊断,以便您了解发生了什么。

    #!/bin/ksh
    wflag=false
    cflag=false
    
    # the first colon means suppress error messages
    # the colon after the x means that -x requires an argument
    while getopts ":cwx:" opt
    do
        echo "opt $opt"
        case "$opt" in
            c)
                cflag=true
                ;;
            w)
                wflag=true
                ;;
            x)
                echo "x is an option, $OPTARG is its argument"
                ;;
            \?)
                echo "invalid option"
                ;;
            *)
                echo "missing argument"
                ;;
        esac
    done
    echo "cflag $cflag"
    echo "wflag $wflag"
    

    现在让我们用几种方式来称呼它:

    $ ./script.ksh -c
    opt [c]
    cflag true
    wflag false
    

    很好。

    $ ./getoptstest.ksh -c -w
    opt [c]
    opt [w]
    cflag true
    wflag true
    

    也不错。

    $ ./getoptstest.ksh -cw
    opt [c]
    opt [w]
    cflag true
    wflag true
    

    还好,但我们的答案已经预示了。

    $ ./getoptstest.ksh '-c -w'
    opt [c]
    opt [?]
    invalid option
    opt [?]
    invalid option
    opt [w]
    cflag true
    wflag true
    

    现在我们正在取得进展。 Korn shell man 页面说:

    Aleading : in optstring 导致 getopts 存储 OPTARG 中的一个无效选项,并且 将 vname 设置为 ?为 unknown option 和 to :当缺少必需的选项参数时 ing。否则,getopts 会打印一条错误消息。

    从最后一个示例之前的示例中可以看出,您可以像-cw 一样运行这些选项。当您传递像'-c -w' 这样的选项时,getopts 将其视为-c -space ---w。因此,除了两个无效选项(---space)之外,它同时看到了 -c-w,这就是设置 both 标志的原因。如果没有前导冒号(这是原始脚本在问题中发布的方式),您应该会收到如下错误消息:

    ./script.ksh: - : unknown option
    ./script.ksh: --: unknown option
    

    如果您仔细观察,您会注意到指示空间和额外的破折号。

    很遗憾,man 页面没有讨论 getopts 处理单独传递或捆绑在一起的参数的能力。

    我不确定我是否理解您的 ksh program.ksh "what up" 示例是否有问题。

    用这些选项和参数试试我修改后的脚本,看看它的其余部分是如何工作的。

    ./script.ksh -x
    ./script.ksh -x foo
    ./script.ksh -z
    ./script.ksh -c bar -w
    

    最后一个很棘手。当找到不以破折号开头的参数并且前面的选项不带参数时,getopts 停止处理,其余参数保留在原位。您可以在while 循环之后使用shift $(($OPTIND - 1)),然后您将能够以通常的方式访问剩余的位置参数。

    不幸的是,getopts 内置的 shell 不能处理像 --version 这样的长选项。外部实用程序getopt 可以,但在使用时可能需要处理一些问题。

    【讨论】:

    • 感谢您提供如此清晰而有帮助的回复。不幸的是getopts 不支持长选项,我想我可能必须找到另一种方法来实现这一点。我会尝试将所有参数存储到一个数组中,并一次处理一个。再次感谢您的帮助!
    • 如果您使用的是 ksh93,它的 getopts 内置扩展名允许长选项。
    • @Alex:你应该知道@jilles 评论说在 ksh93 中,getopts 允许长选项。 official man page 中没有提到它,但它记录在 getopts --man 中。但是,<cough>bloat</cough>.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-05
    • 2012-08-25
    • 2018-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多