Bash中的脚本参数


103

我正在尝试制作应该像这样使用的shell脚本:

ocrscript.sh -from /home/kristoffer/test.png -to /home/kristoffer/test.txt

然后,脚本将ocr将图像文件转换为文本文件。到目前为止,这是我想出的:

#!/bin/bash
export HOME=/home/kristoffer
/usr/local/bin/abbyyocr9 -rl Swedish -if ???fromvalue??? -of ???tovalue??? 2>&1

但是我不知道如何获得-from-to价值观。关于如何做的任何想法?


Answers:


124

您提供给bashscript的参数将出现在变量中$1$2并且$3数字代表该参数。$0是命令本身。

参数由空格分隔,因此,如果在命令中提供-from-to,它们也将以这些变量结尾,因此:

./ocrscript.sh -from /home/kristoffer/test.png -to /home/kristoffer/test.txt

你会得到:

$0    # ocrscript.sh
$1    # -from
$2    # /home/kristoffer/test.png
$3    # -to
$4    # /home/kristoffer/test.txt

省略-from和可能更容易-to,例如:

ocrscript.sh /home/kristoffer/test.png /home/kristoffer/test.txt

然后您将拥有:

$1    # /home/kristoffer/test.png
$2    # /home/kristoffer/test.txt

缺点是您必须以正确的顺序提供它。有一些库可以使在命令行上解析命名参数变得更加容易,但是通常对于简单的shell脚本,如果没有问题,则应该使用简单的方法。

然后,您可以执行以下操作:

/usr/local/bin/abbyyocr9 -rl Swedish -if "$1" -of "$2" 2>&1

$1和周围的双引号$2并不总是必需的,但建议使用双引号,因为如果不将它们放在双引号之间,则某些字符串将不起作用。


69

如果您不完全喜欢使用“ from”和“ to”作为选项名称,那么使用getopts来实现它相当容易:

while getopts f:t: opts; do
   case ${opts} in
      f) FROM_VAL=${OPTARG} ;;
      t) TO_VAL=${OPTARG} ;;
   esac
done

getopts 是一个处理命令行参数并方便地为您解析的程序。

f:t:指定您期望包含2个值的参数(以冒号表示)。喜欢的东西f:t:v说,-v只会被解释为标志。

opts是当前参数的存储位置。该case语句将在此处理。

${OPTARG}包含参数后面的值。${FROM_VAL}例如,/home/kristoffer/test.png如果您像这样运行脚本,将获得该值:

ocrscript.sh -f /home/kristoffer/test.png -t /home/kristoffer/test.txt

正如其他人所建议的那样,如果这是您第一次编写bash脚本,则应该真正阅读一些基础知识。这只是有关如何getopts工作的快速教程。


1
这似乎是一种可读的解决方案。那么,您将如何指定两个标志?
Zelphir Kaltstahl,

@Zelphir,您可以指定两个或多个标志,只需在标志后省略“:”即可。举例来说f:t:vs将是-f some_f -t some_t -v -s
h_s

34

使用变量"$1""$2""$3"等来访问参数。要访问所有这些参数,可以使用"$@"或获取参数计数$#(检查过多或过多的参数可能很有用)。


24

我需要确保我的脚本可以在各种机器,shell甚至cygwin版本之间完全移植。此外,我不得不为其编写脚本的同事是程序员,所以我最终使用了它:

for ((i=1;i<=$#;i++)); 
do

    if [ ${!i} = "-s" ] 
    then ((i++)) 
        var1=${!i};

    elif [ ${!i} = "-log" ];
    then ((i++)) 
        logFile=${!i};  

    elif [ ${!i} = "-x" ];
    then ((i++)) 
        var2=${!i};    

    elif [ ${!i} = "-p" ]; 
    then ((i++)) 
        var3=${!i};

    elif [ ${!i} = "-b" ];
    then ((i++)) 
        var4=${!i};

    elif [ ${!i} = "-l" ];
    then ((i++)) 
        var5=${!i}; 

    elif [ ${!i} = "-a" ];
    then ((i++)) 
        var6=${!i};
    fi

done;

原理:我还包括一个launcher.sh脚本,因为整个操作有几个步骤是彼此独立的(我说的是“准”,因为即使每个脚本都可以独立运行,但它们通常都一起运行) ),两天后我发现,大约一半的同事(无论是程序员还是所有人)都太好了,无法使用启动器文件,遵循“用法”或阅读每次执行某项操作时显示的帮助(HELP)错误,他们把整个事情弄得一团糟,以错误的顺序运行带有参数的脚本,并抱怨脚本无法正常工作。作为一名胆怯的人,我决定彻底检查所有脚本,以确保它们不受同事攻击。上面的代码段是第一件事。


2
我喜欢这个。我在结尾添加部分`其他的回声“:{!我}无效参数$”((我++))网络连接`
CJBS

6

在bash $1中,第一个参数传递给脚本,$2第二个以此类推

/usr/local/bin/abbyyocr9 -rl Swedish -if "$1" -of "$2" 2>&1

因此,您可以使用:

./your_script.sh some_source_file.png destination_file.txt

双引号说明;

考虑以下三个脚本:

# foo.sh
bash bar.sh $1

# cat foo2.sh
bash bar.sh "$1"

# bar.sh
echo "1-$1" "2-$2"

现在调用:

$ bash foo.sh "a b"
1-a 2-b

$ bash foo2.sh "a b"
1-a b 2-

调用时,foo.sh "a b"它调用bar.sh a b(两个参数),并foo2.sh "a b"调用bar.sh "a b"(1个参数)。始终牢记如何在bash中传递和扩展参数,这将为您节省很多麻烦。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.