【问题标题】:Bash: Passing parameters using getoptsBash:使用 getopts 传递参数
【发布时间】:2014-01-17 14:30:02
【问题描述】:

我知道这是一个简单的问题,我一直在研究 getopts 教程和示例,但我被卡住了。如果您查看this 链接,您会发现在@fedorqui 的帮助下,我已经设法编写代码来获取文件中的数组元素。

但是,我需要对输入进行参数化,这样即使我更改了输入的顺序,脚本也能继续工作。

这是我写的第一个代码:

#!/bin/bash

file=$3 row=$1 col=$2 str1="Hata: " str2=". satır " str3=". sütun yok"

if [ $row -gt 3 ]
then
    echo $str1$row$str2$col$str3
elif [ $col -gt 3 ]
then
    echo $str1$row$str2$col$str3
else
    awk 'NR==row{print $col}' row=$row col=$col $file
fi 

现在,脚本像$ ./tablooku.sh 3 2 tablom.dat 一样工作,输出为:

~/Desktop $ ./tablooku.sh 3 2 tablom.dat 
Kopenhag

我需要做的是翻译这段代码,这样当我输入$ ./tablooku.sh -r 3 -c 2 tablom.dat 时,我就能得到脚本工作。

这是我写的运行时卡住的代码:

#!/bin/bash

str1="Hata: "
str2=". satır "
str3=". sütun yok"

while getopts "r:c:f:" opts
do
            case $opts in
            r)     row=$OPTARG echo "-r was triggered, Parameter: $OPTARG";;
            c)     col=$OPTARG echo "-c was triggered, Parameter: $OPTARG";;
            f)     fi=$OPTARG echo "-f was triggered, Parameter: $OPTARG";;
            \?)     printf "Kullanım: %s -r değer -c değer dosya adresi\n" $0
                          exit 2;;
           esac
done

if [ $row -gt 3 ]
then
    echo $str1$row$str2$col$str3
elif [ $col -gt 3 ]
then
    echo $str1$row$str2$col$str3
else
    awk 'NR==r{print $c}' r=$row c=$col $fi
fi

你能告诉我这里有什么问题吗?当我运行命令时,系统输出是:

~/Desktop $ ./go_test.sh -r 3 -c 2 tablom.dat 
-r was triggered, Parameter: 3
-c was triggered, Parameter: 2
./go_test.sh: line 23: [: -gt: unary operator expected
./go_test.sh: line 26: [: -gt: unary operator expected

提示卡住了,我必须使用ctrl+z 来打破等待。看起来我未能将文件位置分配给fi,但我无法解决问题

注意:请记住-r是行,-c是列,最后一个参数是不使用任何选项代码的文件位置(如-f)

更新 1:

我将 if 括号 ] 更改为 ]],将 [ 更改为 [[。现在unary operator expected 错误消失了。现在,提示等待并且不打印-f was triggered, Parameter:... 我仍然使用ctrl+z 来打破等待。

更新 2:

在@grebneke 和@TimK 的建议下,我添加了分号并将fi 参数更改为fil。这样,我就可以使脚本正常工作。但是,还有一个小问题。如果我输入$ ./tablooku.sh -r 3 -c 2 -f tablom.dat,代码就可以工作。但是,我需要它运行而无需编写-f。有可能吗?

【问题讨论】:

    标签: linux bash shell getopts


    【解决方案1】:

    在这些行中:

            r)     row=$OPTARG echo "-r was triggered, Parameter: $OPTARG";;
            c)     col=$OPTARG echo "-c was triggered, Parameter: $OPTARG";;
            f)     fi=$OPTARG echo "-f was triggered, Parameter: $OPTARG";;
    

    您只为该行的其余部分分配row/col/fi。在分配后添加分号,它将在脚本的其余部分保持分配:

            r)     row=$OPTARG; echo "-r was triggered, Parameter: $OPTARG";;
            c)     col=$OPTARG; echo "-c was triggered, Parameter: $OPTARG";;
            f)     fi=$OPTARG; echo "-f was triggered, Parameter: $OPTARG";;
    

    编辑 <deleted, I misunderstood the question>

    编辑 2 要在使用getopts 后获取剩余参数,您必须像这样shift

    while getopts "r:c:" opts
    do
    ...
    done
    
    shift $(( $OPTIND-1 ))
    
    # Now, $1, $2 etc are your arguments as you are used to:
    $ ./tablooku.sh -r 3 -c 2 tablom.dat
    # $1 will be "tablom.dat"
    

    【讨论】:

    • 感谢您的提示,但不幸的是,它不起作用。脚本的结果还是一样: ~/Desktop $ ./go_test.sh -r 3 -c 2 tablom.dat r wastriggered, Parameter: 3 c wastriggered, Parameter: 2 (这是提示等待的地方对于某些东西)我无法使上面的代码看起来像代码:(
    • 现在,不知何故我设法让它工作,但我必须在文件位置之前使用 -f。此外,我将fi 参数名称更改为fil。我的意思是,如果我使用$ ./tablooku.sh -r 3 -c 2 -f tablom.dat,脚本就可以工作。如何更改代码,以便我不必在位置前写-f
    • 新的awk,旧的在哪里,不返回正确的值。使用原始值,我可以获得正确的值,但现在我的问题是不要在文件参数之前使用-f。你知道怎么做吗(请查看我的更新 2)
    • @iso_9001_ 请参见上面的编辑 2
    • 现在它可以工作了,我真的很高兴 :) 非常感谢您的努力。亲切的问候
    【解决方案2】:

    您在设置 $row、$col 和 $fi 的位置缺少分号。

            case $opts in
            r)     row=$OPTARG echo "-r was triggered, Parameter: $OPTARG";;
            c)     col=$OPTARG echo "-c was triggered, Parameter: $OPTARG";;
            f)     fi=$OPTARG echo "-f was triggered, Parameter: $OPTARG";;
            \?)     printf "Kullanım: %s -r değer -c değer dosya adresi\n" $0
                          exit 2;;
           esac
    

    应该是(echo 之前的分号):

            case $opts in
            r)     row=$OPTARG ; echo "-r was triggered, Parameter: $OPTARG";;
            c)     col=$OPTARG ; echo "-c was triggered, Parameter: $OPTARG";;
            f)     fi=$OPTARG ; echo "-f was triggered, Parameter: $OPTARG";;
            \?)     printf "Kullanım: %s -r değer -c değer dosya adresi\n" $0
                          exit 2;;
           esac
    

    如果没有这些分号,您的命令将无法按预期运行,正如您可以看到查看 bash -x 的输出并使用 -gt 检查这些行:

    bash-[576]$ bash -x foo.bash -r 3 -c 3 -f foo
    + str1='Hata: '
    + str2='. satır '
    + str3='. sütun yok'
    + getopts r:c:f: opts
    + case $opts in
    + row=3
    + echo '-r was triggered, Parameter: 3'
    -r was triggered, Parameter: 3
    + getopts r:c:f: opts
    + case $opts in
    + col=3
    + echo '-c was triggered, Parameter: 3'
    -c was triggered, Parameter: 3
    + getopts r:c:f: opts
    + case $opts in
    + fi=foo
    + echo '-f was triggered, Parameter: foo'
    -f was triggered, Parameter: foo
    + getopts r:c:f: opts
    + '[' -gt 3 ']'
    foo.bash: line 18: [: -gt: unary operator expected
    + '[' -gt 3 ']'
    foo.bash: line 20: [: -gt: unary operator expected
    + awk 'NR==r{print $c}' r= c=
    

    用分号:

    bash-[574]$ bash -x foo.bash -r 3 -c 3 -f foo
    + str1='Hata: '
    + str2='. satır '
    + str3='. sütun yok'
    + getopts r:c:f: opts
    + case $opts in
    + row=3
    + echo '-r was triggered, Parameter: 3'
    -r was triggered, Parameter: 3
    + getopts r:c:f: opts
    + case $opts in
    + col=3
    + echo '-c was triggered, Parameter: 3'
    -c was triggered, Parameter: 3
    + getopts r:c:f: opts
    + case $opts in
    + fi=foo
    + echo '-f was triggered, Parameter: foo'
    -f was triggered, Parameter: foo
    + getopts r:c:f: opts
    + '[' 3 -gt 3 ']'
    + '[' 3 -gt 3 ']'
    + awk 'NR==r{print $c}' r=3 c=3 foo
    

    再次查看带有-gt 的行。因此,如果没有 ;,您的 $row、$col 和 $fi 变量设置不会传播。

    【讨论】:

    • 感谢您的详细解答。请在我的 OP 上查看 update2
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    • 2014-05-23
    • 2012-10-24
    • 1970-01-01
    • 2021-04-29
    相关资源
    最近更新 更多