Linux学习--No.11 设置脚本参数、选项

之前使用生信软件时,会加好多选项参数。这次简单学习下在自己的脚本中,添加选项及参数。最后再学习一个获得用户输入的常用命令read

要点一、命令行参数

1、基础用法--位置参数变量

bash shell 给输入到命令行的所有参数,定义了位置参数(positional parameter)的特殊变量,形式为标准的数字,举一例就明白了。

./test.sh 10 20
  • $0 一般是脚本名 ./test.sh
  • $1 是第一个参数 10
  • $2 是第二个参数 20

以此类推,直到第9个参数 $9,用户可以在命令行赋值给相应的变量。如上述将数值10、20分别赋值给脚本test.sh中的$1、$2位置参数变量,从而可以在脚本中使用这些变量。如下是一个简单的例子

cat test1.sh
#!/bin/bash
#
total=$[ $1*$2 ]
echo The first parameter is $1
echo The second parameter is $2
echo total value is $total
./test1.sh 3 9

除了上述用数字赋值给位置参数变量外,也可以用文本字符串赋值。如果含空格,加上引号(单双均可)

2、特殊的位置参数变量

2.1、 $0

$0 参数,一般就是指脚本名。但是如果用全路径(绝对/相对)执行脚本时,$0同样会含有路径名。此时可以用basename命令进行简化。

cat test2.sh
#!/bin/bash
#
cat test2.sh 
echo the first name is $0
echo the new name is $(basename $0)   #命令替换
./test3.sh
  • 注意观察输出的两处不同,basename命令可以打印目录或者文件(如脚本)的基本名称。

2.2、 多于9个变量

当然也可以输入不止9个变量,不过在脚本引用第9个以后的参数时,要加上花括号 。比如${11} 即表示第11个位置参数,而不能简单使用$11。(只是理论上有这种用法,一般都用不到这么多参数吧)

3、遍历位置参数变量

3.1、储存所有参数方法

  • $@变量默认储存了在命令行输入的所有参数,从而可在脚本中搭配for语句,遍历所有位置参数变量
cat test3.sh
#!/bin/bash
#
echo
#
count=1
for param in "$@"   
do
    echo "\$@ Parameter #$count = $param"  #注意转义符的使用。
    count=$[ $count + 1 ]
done
./test3.sh jim tom sam
#该脚本会逐一迭代"$@"里的参数值,用于执行循环命令

与之类似的变量是$*,但是$*是把所有输入的参数当做一个整体使用(一个含空格的字符串可能更好理解)。
此外还有一个挺有用的变量$#,它能统计命令行输入了多少个参数。这常用于提醒用户输入正确数目的参数。

3.2、不断前移变量法

  • shift命令可以将每个参数变量都向前移动一个位置,比如$2的值移动到$1,$3的值移动到$2,......而原先$1的值会被删除($0不受影响)。如此不断使用shift命令也可以实现遍历所有位置参数变量。(我觉得这种方法可能更常用)
cat test4.sh
#!/bin/bash
#
echo
count=1
while [ -n "$1" ]    
do
    echo "Parameter #$count = $1"
    count=$[ $count + 1 ]
    shift  
done
  • 因为每次循环都会前移一个变量,所以脚本中只要考虑$1位置参数变量即可。
  • [ -n "$1" ] 的-n用于判断$1的字符串长度是否大于0,作为whlie语句的执行依据。
./test4.sh jim tom sam   
#效果同前法

要点二、命令行选项

  • 书写格式:单破折号后面跟一个字母,比如-a
  • 如果说命令行参数能够提供数据的话,那么命令行选项则能改变命令的行为。即一个选项对应一种特色的功能。可以联想我们之前学习Linux命令时所接触的一些选项,比如 ls -l
  • 一般来说分为有效选项与无效选项,后者即为未定义选项。因此脚本命令要有区分的能力,常搭配case语句。case语句会检查每个参数是不是有效选项,是的话,就运行对应case语句中的命令。

在下面的一些例子中,仅举了十分简单的输出命令。不过记住选项的功能是很强大的。

1、常规处理方法

cat test5.sh
#!/bin/bash
#
echo
while [ -n "$1" ]
do
    case "$1" in           #case用法,确认参数属于下列哪四种情况之一
        -a) echo "Found the -a option" ;;    # 双分号也是固定格式   
        -b) echo "Found the -b option" ;;
        -c) echo "Found the -c option" ;;
        -*) echo "$1 is not an option" ;;
    esac    #标志结束(case 倒过来了)
    shift  #前移参数
done
  • 结合上例,学习下case语句的用法;
  • 搭配shift命令,遍历所有选项。
  • -*)处代码设置了非以上三种有效选项情况下的报错语句。
./test5.sh -a -cb -e
  • 选项合并书写也是一种很常见的,友好的写法。

特殊情况1、识别命令行中同时输入的选项与参数

  • 办法:在选项与参数间使用双破折线。
  • 当脚本遇到双破折线时,停止处理选项,并将剩下的参数都当做命令行参数(其实并非这么“智能”,需要在脚本代码中予以交代的)。
cat test6.sh
#!/bin/bash
#
echo
while [ -n "$1" ]
do
    case "$1" in           
        -a) echo "Found the -a option" ;;
        -b) echo "Found the -b option" ;;
        -c) echo "Found the -c option" ;;
        --) shift      # 先将参数前移,再退出循环,进行参数处理
            break ;;
        -*) echo "$1 is not an option" ;;
    esac    
    shift  #前移参数
done
#处理完选项,再处理参数~
count=1
for param in $@
do 
    echo "Parameter #$count: $param"
    count=$[ $count + 1 ]
done
./test9.sh -a -cb -- 5 9 6 3

特殊情况2、处理带值(参数)的选项

cat test7.sh
#!/bin/bash
#
echo
while [ -n "$1" ]
do
    case "$1" in           
        -a) echo "Found the -a option" ;;
        -b) param="$2"
            echo "Found the -b option, with parameter value $param" ;;     
            shift ;;    
        -c) echo "Found the -c option" ;;
        --) shift     
            break ;;
        -*) echo "$1 is not an option" ;;
    esac    
    shift  
done
#
count=1
for param in $@
do 
    echo "Parameter #$count: $param"
    count=$[ $count + 1 ]
done
  • 这里 -b 选项需要有一个参数,命令行书写要注意。
  • 因为-b 选项加上连带参数占据两个位置,要前移两次参数。
./test7.sh -c -b 5 -d -a

2、getopt命令读取选项、参数

  • getopt命令可以接受一系列任意形式的命令行的选项和参数,并自动将它们转换成适当的格式。
  • 用法:getopt optstring parameters,其中optstring定义了命令行有效的选项字母;如果为需要参数数据的选项,则在字母后面加一个冒号。如果命令行输入了不属于定义范围的无效选项,会返回报错信息。parameters为用户输入的选项参数。
cat test8.sh
#!/bin/bash
#
set -- $(getopt -q ab:cd "$@")
echo
while [ -n "$1" ]
do
    case "$1" in
#以下代码与前相同,不赘述
  • ab:cd表getopt识别 -a、-c、-d选项,以及带有参数的-b选项;以及后面的数据参数;
  • set --将getopt命令生成的格式化后的版本来替换已有的命令行选项和参数(排除掉无效参数);
  • getopt-p参数能够忽略无效选项的报错信息。

可能会觉得与上一个脚本没什么区别,唯一的不同就是加入了getopt命令来帮助格式化命令行参数。优势的话就是提前筛选了有效选项,并且不用加--来把选项与参数分开了。(那么脚本里的相应代码可以省略吗?因为无法演示,存疑!)

3、getopts命令读取选项、参数

getoptsgetopt的高级版。主要区别为getopt将命令行上的选项和参数处理后一次性全部输出;getopts则是一次只处理命令行上检测到的一个选项。

  • 用法:getopts optstring variable optstring值同前,variable为储存迭代用户输入的选项的变量名。若发现未定义的选项,会输出成?问号。并且getopts知道何时停止处理选项,并将参数留给用户处理。见下面的例子就好理解了
cat test9.sh
#!/bin/bash
#
echo 
while getopts : ab:cd opt   
do 
    case "$opt" in
        a) echo "Found the -a option" ;;  #注意这里的选项书写,不用加破折号
        b) echo "Found the -b option, witn value $OPTARG" ;; 
        c) echo "Found the -c option" ;;
        *) echo "Unknown option: $opt" ;;   
    esac
done
#
shift $[ $OPTIND - 1 ]
#
echo 
count=1
for param in "$@"
do
    echo "Parameter $count: $param"
    count=$[ $count + 1 ]
done 

上述代码涉及到关于getopts的两个重要环境变量

  • OPTARG变量会在选项带有参数数据时,保存该参数值;见上-b选项处理参数的用法。
  • OPTIND变量保存了参数列表中getopts正在处理的参数位置;见上,配合shift开始处理参数时的用法。
./test9.sh -ab test1 -c 10 15 95

综上就是关于脚本从参数、选项获得输入的学习,最后再学习另一个常用的读取命令read

read命令从键盘输入或一个文件中接受输入;在收到输入后,read命令会将数据放进一个变量(名字自己随便取),以供使用.

(1)键盘输入--实现交互式操作

#!/bin/bash
#
echo -n "Enter your name: "
read name    #将变量命名为name
echo "Hello $name, welcome to my home"

上述代码实现了接受键盘输入的数据,将其存到变量 name,然后使用变量。此用法还可配合 -p ,-t(超时),-s(隐藏读取) 选项使用(详见p306)

(2)文本文件读取

  • 前期准备文本文件
cat test.txt
how are you
i am fine
that is great
  • read读取
#!/bin/bash
#
count=1
cat test.txt | while read line  
#cat的结果通过管道符传给含有read命令(逐行读取)的while命令
do
    echo "Line $count: $line"
    count=$[ $count + 1 ]
done

循环会持续通过read命令处理文件中的行,直到read命令以非零退出状态码退出。

以上就是处理用户输入的脚本参数

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容