Linux shell 脚本编程-基础篇 (四)

(超详细)Linux Shell 编程 Linuxshell编程 Shell是一个命令解释器,它的作用是解释执行用户输入的命令及程序等。 用户每输入一条命令,Shell就执行一条。这种从键盘输入命令,就可以立即得到回应的对话方式,称为交互的方式。.................................... 阅读详情

继 Linux shell 脚本编程-基础篇 (三)

 

4. 处理用户输入


脚本还得能够与使用者进行交互。bash shell 提供了一些不同的方法来从用户处获得数据,包括命令行参数(添加在命令后的数据)、命令行选项(可修改

命令行为的单个字母)以及直接从键盘读取输入的能力。

 

4.1 命令行参数
-----------------------------------------------------------------------------------------------------------------------------------------
向 shell 脚本传递数据的最基本方法是使用命令行参数。命令行参数允许在运行脚本时向命令行添加数据。

    ./addem 10 30

本例向脚本 addem 传递了两个命令行参数(10和30)。脚本会通过特殊的变量来处理命令行参数。


4.1.1 读取参数
-----------------------------------------------------------------------------------------------------------------------------------------
bash shell 会将一些称为位置参数(positional parameter)的特殊变量分配给输入到命令行中的所有参数。这也包括 shell 所执行的脚本名称。位置参数
变量是标准的数字:$0是程序名,$1是第一个参数,$2是第二个参数,依次类推,直到第九个参数$9。

示例:
    [devalone@devalone 14]$ cat test1.sh
    #!/bin/bash
    # using one command line parameter
    #
    factorial=1
    for (( number=1; number <= $1; number++ ))
    do
        factorial=$[ $factorial * $number ]
    done
    echo The factorial of $1 is $factorial

运行:
    [devalone@devalone 14]$ test1.sh 5
    The factorial of 5 is 120

可以在 shell 脚本中像使用其他变量一样使用 $1 变量。shell 脚本会自动将命令行参数的值分配给变量,不需要作任何处理。

如果需要输入更多的命令行参数,则每个参数都必须用空格分开。

示例:
    [devalone@devalone 14]$ cat test2.sh
    #!/bin/bash
    # testing two command line parameters
    #
    total=$[ $1 * $2 ]
    echo The first paramter is $1.
    echo The second parameter is $2.
    echo The total value is $total.

运行:
    [devalone@devalone 14]$ test2.sh 2 5
    The first paramter is 2.
    The second parameter is 5.
    The total value is 10.

shell 会将每个参数分配给对应的变量。

也可以在命令行上用文本字符串:

示例:
    [devalone@devalone 14]$ cat test3.sh
    #!/bin/bash
    # testing string parameters
    #
    echo Hello $1, glad to meet you

运行:
    [devalone@devalone 14]$ test3.sh deva
    Hello deva, glad to meet you

shell 将输入到命令行的字符串值传给脚本。但碰到含有空格的文本字符串时就会出现问题:

运行:
    [devalone@devalone 14]$ test3.sh deva Richard
    Hello deva, glad to meet you

每个参数都是用空格分隔的,所以 shell 会将空格当成两个值的分隔符。要在参数值中包含空格,必须要用引号(单引号或双引号均可)。

运行:
    [devalone@devalone 14]$ test3.sh 'deva Richard'
    Hello deva Richard, glad to meet you


    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    将文本字符串作为参数传递时,引号并非数据的一部分。它们只是表明数据的起止位置。

如果脚本需要的命令行参数不止 9 个,仍然可以处理,但是需要稍微修改一下变量名。在第 9 个变量之后,必须在变量数字周围加上花括号,比如${10}。

示例:
    [devalone@devalone 14]$ cat test4.sh
    #!/bin/bash
    # handling lots of parameters
    #
    total=$[ ${10} * ${11} ]
    echo The 10th parameter is ${10}
    echo The 11th parameter is ${11}
    echo The total is $total

运行:
    [devalone@devalone 14]$ test4.sh 1 2 3 4 5 6 7 8 9 10 12
    The 10th parameter is 10
    The 11th parameter is 12
    The total is 120

 

4.1.2 读取脚本名
-----------------------------------------------------------------------------------------------------------------------------------------
可以用 $0 参数获取 shell 在命令行启动的脚本名。这在编写多功能工具时很方便。

示例:
    [devalone@devalone 14]$ cat test5.sh
    #!/bin/bash
    # Testing the $0 parameter
    #
    echo The zero parameter is set to: $0
    #

运行:
    [devalone@devalone 14]$ test5.sh
    The zero parameter is set to: ./test5.sh

    [devalone@devalone 14]$ bash test5.sh
    The zero parameter is set to: test5.sh

运行方式不同,结果也不同。当传给 $0 变量的实际字符串不仅仅是脚本名,而是完整的脚本路径时,变量 $0 就会使用整个路径。

运行:

    [devalone@devalone 14]$ bash /home/devalone/study/shell-script/14/test5.sh
    The zero parameter is set to: /home/devalone/study/shell-script/14/test5.sh    

如果要编写一个根据脚本名来执行不同功能的脚本,就得做点额外工作。得把脚本的运行路径给剥离掉。另外,还要删除与脚本名混杂在一起的命令。

幸好有个方便的小命令可以帮到我们。basename 命令会返回不包含路径的脚本名。

示例:

    [devalone@devalone 14]$ cat test5b.sh
    #!/bin/bash
    # using basename with the $0 parameter
    #
    name=$(basename $0)
    echo The script name is: $name
    #

运行:
    [devalone@devalone 14]$ bash /home/devalone/study/shell-script/14/test5b.sh
    The script name is: test5b.sh

    [devalone@devalone 14]$ test5b.sh
    The script name is: test5b.sh

现在好多了。可以用这种方法来编写基于脚本名执行不同功能的脚本:

示例:
    [devalone@devalone 14]$ cat test6.sh
    #!/bin/bash
    # testing a multi-function script
    #
    name=$(basename $0)
    #
    if [ $name = "addem" ]
    then
        total=$[ $1 + $2 ]
    elif [ $name = "multem" ]
    then
        total=$[ $1 * $2 ]
    fi

    echo
    echo The calculated value is $total

运行:
    [devalone@devalone 14]$ cp test6.sh addem

    [devalone@devalone 14]$ ls -l *em
    -rwxrwxr-x. 1 devalone devalone 221 7月   6 16:24 addem
    lrwxrwxrwx. 1 devalone devalone   8 7月   6 16:25 multem -> test6.sh

    [devalone@devalone 14]$ addem 2 5

    The calculated value is 7
    [devalone@devalone 14]$ multem 2 5

    The calculated value is 10

 

4.1.3 测试参数
-----------------------------------------------------------------------------------------------------------------------------------------
在 shell 脚本中使用命令行参数时要小心些。如果脚本不加参数运行,可能会出问题。

运行:
    [devalone@devalone 14]$ addem 2
    ./addem:行8: 2 +  : 语法错误: 需要操作数 (错误符号是 "+  ")

    The calculated value is

当脚本认为参数变量中会有数据而实际上并没有时,脚本很有可能会产生错误消息。在使用参数前一定要检查其中是否存在数据。

示例:
    [devalone@devalone 14]$ cat test7.sh
    #!/bin/bash
    # testing parameters befor use
    #
    if [ -n "$1" ]
    then
        echo Hello $1, glad to meet you
    else
        echo Sorry, you did not identify yourself
    fi

运行:
    [devalone@devalone 14]$ test7.sh
    Sorry, you did not identify yourself
    
    [devalone@devalone 14]$ test7.sh Michael
    Hello Michael, glad to meet you
    


4.2 特殊参数变量
-----------------------------------------------------------------------------------------------------------------------------------------
在 bash shell 中有些特殊变量,它们会记录命令行参数。

 

4.2.1 参数统计
-----------------------------------------------------------------------------------------------------------------------------------------
特殊变量 $# 含有脚本运行时携带的命令行参数的个数。可以在脚本中任何地方使用这个特殊变量,就跟普通变量一样。

示例:
    [devalone@devalone 14]$ cat test8.sh
    #!/bin/bash
    # getting the number of parameters
    #
    echo there are $# parameters supplied

运行:
    [devalone@devalone 14]$ test8.sh
    there are 0 parameters supplied
    [devalone@devalone 14]$ test8.sh 1 2 3 4 5
    there are 5 parameters supplied
    [devalone@devalone 14]$ test8.sh 1 2 3 4 5 6  7 8 9 10
    there are 10 parameters supplied

    [devalone@devalone 14]$ test8.sh Michael Dan
    there are 2 parameters supplied
    [devalone@devalone 14]$ test8.sh "Michael Dan"
    there are 1 parameters supplied

在使用参数前测试参数的总数:
    [devalone@devalone 14]$ cat test9.sh
    #!/bin/bash
    # testing parameters
    #
    if [ $# -ne 2 ]
    then
        echo
        echo Usage: test9.sh a b
        echo
    else
        total=$[ $1 + $2 ]
        echo
        echo the total is $total
        echo
    fi

运行:
    [devalone@devalone 14]$ test9.sh

    Usage: test9.sh a b

    [devalone@devalone 14]$ test9.sh 10

    Usage: test9.sh a b

    [devalone@devalone 14]$ test9.sh 10 15

    the total is 25

if-then 语句用 -ne 测试命令行参数数量。如果参数数量不对,会显示一条错误消息告知脚本的正确用法。

这个变量还提供了一个简便方法来获取命令行中最后一个参数,完全不需要知道实际上到底用了多少个参数。不过要实现这一点,得稍微多花点工夫。

可能会觉得既然$#变量含有参数的总数,那么变量 ${$#} 就代表了最后一个命令行参数变量。试试看会发生什么:

    [devalone@devalone 14]$ cat badtest1.sh
    #!/bin/bash
    # testing grabbing last parameter
    #
    echo The last parameter was ${$#}
    #

运行:
    [devalone@devalone 14]$ ./badtest1.sh 10
    The last parameter was 3681

表明不能在花括号内使用美元符。必须将美元符换成感叹号。很奇怪,但的确管用。

    [devalone@devalone 14]$ cat test10.sh
    #!/bin/bash
    # grabbing the last parameter
    #
    parameter=$#
    echo
    echo the parameter count is $parameter
    echo the last parameter is ${!#}
    echo

运行:
    [devalone@devalone 14]$ test10.sh 1 2 3 4 5

    the parameter count is 5
    the last parameter is 5

这个测试将 $# 变量的值赋给了变量 params,然后也按特殊命令行参数变量的格式使用了该变量。两种方法都没问题。重要的是要注意,当命令行上没有
任何参数时,$# 的值为 0,params 变量的值也一样,但 ${!#} 变量会返回命令行用到的脚本名。


4.2.2 抓取所有的数据
-----------------------------------------------------------------------------------------------------------------------------------------
有时候需要抓取命令行上提供的所有参数。这时候不需要先用 $# 变量来判断命令行上有多少参数,然后再进行遍历,可以使用一组其他的特殊变量来解决
这个问题。

$* 和 $@ 变量可以用来轻松访问所有的参数。这两个变量都能够在单个变量中存储所有的命令行参数。

$* 变量会将命令行上提供的所有参数当作一个单词保存。这个单词包含了命令行中出现的每一个参数值。基本上 $* 变量会将这些参数视为一个整体,而
不是多个个体。

$@ 变量会将命令行上提供的所有参数当作同一字符串中的多个独立的单词。这样就能够遍历所有的参数值,得到每个参数。这通常通过 for 命令完成。

示例:
    [devalone@devalone 14]$ cat test11.sh
    #!/bin/bash
    # testing $* and $@
    #
    echo
    echo "Using the \$* method: $*"
    echo "Using the \$@ method: $@"

运行:
    [devalone@devalone 14]$ test11.sh rich barbara katie jessica

    Using the $* method: rich barbara katie jessica
    Using the $@ method: rich barbara katie jessica

从表面上看,两个变量产生的是同样的输出,都显示出了所有命令行参数。

示例:
    [devalone@devalone 14]$ cat test12.sh
    #!/bin/bash
    # testing $* and $@
    #
    echo
    count=1
    #
    for param in "$*"
    do
        echo "\$* parameter #$count = $param"
        count=$[ $count + 1 ]
    done
    #
    echo
    count=1
    #
    for param in "$@"
    do
        echo "\$@ parameter #$count = $param"
        count=$[ $count + 1 ]
    done

运行:
    [devalone@devalone 14]$ test12.sh rich barbara katie jessica

    $* parameter #1 = rich barbara katie jessica

    $@ parameter #1 = rich
    $@ parameter #2 = barbara
    $@ parameter #3 = katie
    $@ parameter #4 = jessica

现在清楚多了。通过使用 for 命令遍历这两个特殊变量,能看到它们是如何不同地处理命令行参数的。$* 变量会将所有参数当成单个参数,而 $@ 变量会
单独处理每个参数。这是遍历命令行参数的一个绝妙方法。


4.3 移动变量
-----------------------------------------------------------------------------------------------------------------------------------------
bash shell 的 shift 命令能够用来操作命令行参数。跟字面上的意思一样,shift 命令会根据它们的相对位置来移动命令行参数。

在使用 shift 命令时,默认情况下它会将每个参数变量向左移动一个位置。所以,变量 $3 的值会移到 $2 中,变量 $2 的值会移到 $1 中,而变量 $1 的
值则会被删除(注意,变量 $0 的值,也就是程序名,不会改变)。

这是遍历命令行参数的另一个好方法,尤其是在不知道到底有多少参数时。可以只操作第一个参数,移动参数,然后继续操作第一个参数。

示例:
    [devalone@devalone 14]$ cat test13.sh
    #!/bin/bash
    # demonstrating the shift command
    echo
    count=1
    while [ -n "$1" ]
    do
        echo "Parameter #$count = $1"
        count=$[ $count + 1 ]
        shift
    done

运行:
    [devalone@devalone 14]$ test13.sh rich barbara katie jessica

    Parameter #1 = rich
    Parameter #2 = barbara
    Parameter #3 = katie
    Parameter #4 = jessica


这个脚本通过测试第一个参数值的长度执行了一个 while 循环。当第一个参数的长度为零时,循环结束。测试完第一个参数后,shift 命令会将所有参数的
位置移动一个位置。


    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    使用 shift 命令的时候要小心。如果某个参数被移出,它的值就被丢弃了,无法再恢复

    
也可以一次性移动多个位置,只需要给 shift 命令提供一个参数,指明要移动的位置数就行了。

示例:
    [devalone@devalone 14]$ cat test14.sh
    #!/bin/bash
    # demonstrating a multi-position shift
    #
    echo
    echo "The original parameters: $*"
    shift 2
    echo "Here's the new first parameter: $1"
    echo

运行:
    [devalone@devalone 14]$ test14.sh 1 2 3 4 5

    The original parameters: 1 2 3 4 5
    Here's the new first parameter: 3

通过使用 shift 命令的参数,就可以轻松地跳过不需要的参数。


4.4 处理选项
-----------------------------------------------------------------------------------------------------------------------------------------
选项是跟在单破折线后面的单个字母,它能改变命令的行为。


4.4.1 查找选项
-----------------------------------------------------------------------------------------------------------------------------------------
表面上看,命令行选项也没什么特殊的。在命令行上,它们紧跟在脚本名之后,就跟命令行参数一样。实际上,如果愿意,可以像处理命令行参数一样处理
命令行选项。


● 处理简单选项
-----------------------------------------------------------------------------------------------------------------------------------------
在前面的 test13.sh 脚本中,看到了如何使用 shift 命令来依次处理脚本程序携带的命令行参数。也可以用同样的方法来处理命令行选项。

在提取每个单独参数时,用 case 语句来判断某个参数是否为选项:

[devalone@devalone 14]$ cat test15.sh
#!/bin/bash
# extracting command line options as parameters
#
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";;
        *) echo "$1 is not an option";;
    esac
    shift
done

运行:
    [devalone@devalone 14]$ test15.sh -a -b -c -d

    found the -a option
    found the -b option
    found the -c option
    -d is not an option

case 语句会检查每个参数是不是有效选项。如果是的话,就运行对应 case 语句中的命令。不管选项按什么顺序出现在命令行上,这种方法都适用。

运行:
    [devalone@devalone 14]$ test15.sh -d -c -a

    -d is not an option
    found the -c option
    found the -a option


● 分离参数和选项
-----------------------------------------------------------------------------------------------------------------------------------------
经常遇到想在 shell 脚本中同时使用选项和参数的情况。Linux 中处理这个问题的标准方式是用特殊字符来将二者分开,该字符会告诉脚本何时选项结束
以及普通参数何时开始。

对 Linux 来说,这个特殊字符是双破折线(--)。shell会用双破折线来表明选项列表结束。在双破折线之后,脚本就可以放心地将剩下的命令行参数当作
参数,而不是选项来处理了。

示例:
    [devalone@devalone 14]$ cat test16.sh
    #!/bin/bash
    # extracting options and parameters
    #
    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

在遇到双破折线时,脚本用 break 命令来跳出 while 循环。由于过早地跳出了循环,我们需要再加一条 shift 命令来将双破折线移出参数变量。

运行:
    [devalone@devalone 14]$ test16.sh -c -a -b -- test1 test2 test3

    found the -c option
    found the -a option
    found the -b option
    parameter #1: test1
    parameter #2: test2
    parameter #3: test3

当脚本遇到双破折线时,它会停止处理选项,并将剩下的参数都当作命令行参数。


● 处理带值的选项
-----------------------------------------------------------------------------------------------------------------------------------------
有些选项会带上一个额外的参数值。在这种情况下,命令行看起来像下面这样:

    $ ./testing.sh -a test1 -b -c -d test2

当命令行选项要求额外的参数时,脚本必须能检测到并正确处理。下面是如何处理的示例:

    [devalone@devalone 14]$ cat test17.sh
    #!/bin/bash
    # extracting options and values
    #
    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

运行:
    [devalone@devalone 14]$ test17.sh -a -b test1 -d

    found the -a option
    found the -b option, with parameter value test1
    -d is not an option

在这个例子中,case 语句定义了三个它要处理的选项。-b 选项还需要一个额外的参数值。由于要处理的参数是 $1,额外的参数值就应该位于$2(因为所有
的参数在处理完之后都会被移出)。只要将参数值从 $2 变量中提取出来就可以了。当然,因为这个选项占用了两个参数位,所以还需要使用 shift 命令
多移动一个位置。

只用这些基本的特性,整个过程就能正常工作,不管按什么顺序放置选项(但要记住包含每个选项相应的选项参数)。

运行:
    [devalone@devalone 14]$ test17.sh -b test1 -a -d

    found the -b option, with parameter value test1
    found the -a option
    -d is not an option

现在 shell 脚本中已经有了处理命令行选项的基本能力,但还有一些限制。比如,如果想将多个选项放进一个参数中时,它就不能工作了。

    [devalone@devalone 14]$ test17.sh -ac
    -ac is not an option

在 Linux中,合并选项是一个很常见的用法,而且如果脚本想要对用户更友好一些,也要给用户提供这种特性。幸好,有另外一种处理选项的方法能够帮忙。


4.4.2 使用getopt 命令
-----------------------------------------------------------------------------------------------------------------------------------------
getopt 命令是一个在处理命令行选项和参数时非常方便的工具。它能够识别命令行参数,从而在脚本中解析它们时更方便。

 

● 命令的格式
-----------------------------------------------------------------------------------------------------------------------------------------
getopt 命令可以接受一系列任意形式的命令行选项和参数,并自动将它们转换成适当的格式。它的命令格式如下:

    getopt optstring parameters

optstring 是这个过程的关键所在。它定义了命令行有效的选项字母,还定义了哪些选项字母需要参数值。

首先,在 optstring 中列出要在脚本中用到的每个命令行选项字母。然后,在每个需要参数值的选项字母后加一个冒号。getopt 命令会基于此定义的
optstring 解析提供的参数。

下面是个 getopt 如何工作的简单例子:

    [devalone@devalone 14]$ getopt ab:cd -a -b test1 -cd test2 test3
     -a -b test1 -c -d -- test2 test3

optstring 定义了四个有效选项字母:a、b、c和d。冒号(:)被放在了字母 b 后面,因为 b 选项需要一个参数值。当 getopt 命令运行时,它会检查提供
的参数列表(-a -b test1 -cd test2 test3),并基于提供的 optstring 进行解析。注意,它会自动将 -cd 选项分成两个单独的选项,并插入双破折线来
分隔行中的额外参数。

如果指定了一个不在 optstring 中的选项,默认情况下,getopt 命令会产生一条错误消息:

    [devalone@devalone 14]$ getopt ab:cd -a -b test1 -cde test2 test3
    getopt: invalid option -- 'e'
     -a -b test1 -c -d -- test2 test3

如果想忽略这条错误消息,可以在命令后加 -q 选项:

    [devalone@devalone 14]$ getopt -q ab:cd -a -b test1 -cde test2 test3
     -a -b 'test1' -c -d -- 'test2' 'test3'
 
注意,getopt 命令选项必须出现在 optstring 之前。

 

● 在脚本中使用 getopt
-----------------------------------------------------------------------------------------------------------------------------------------
可以在脚本中使用 getopt 来格式化脚本所携带的任何命令行选项或参数,但用起来略微复杂。方法是用 getopt 命令生成的格式化后的版本来替换已有的
命令行选项和参数。用 set 命令能够做到。

set 命令的选项之一是双破折线(--),它会将命令行参数替换成 set 命令的命令行值。

然后,该方法会将原始脚本的命令行参数传给 getopt 命令,之后再将 getopt 命令的输出传给 set 命令,用 getopt 格式化后的命令行参数来替换原始的
命令行参数,看起来如下所示:

    set -- $(getopt -q ab:cd "$@")

现在原始的命令行参数变量的值会被 getopt 命令的输出替换,而 getopt 已经为我们格式化好了命令行参数。

利用该方法,现在就可以写出能帮我们处理命令行参数的脚本。

示例:
    [devalone@devalone 14]$ cat test18.sh
    #!/bin/bash
    # extract command line options and values with getopt
    #
    set -- $(getopt -q ab:cd "$@")
    #
    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

运行:
    [devalone@devalone 14]$ test18.sh -ac

    found the -a option
    found the -c option    
    
    [devalone@devalone 14]$ test18.sh -a -b test1 -cd test2 test3 test4

    found the -a option
    found the -b option, with parameter value 'test1'
    found the -c option
    -d is not an option
    parameter #1: 'test2'
    parameter #2: 'test3'
    parameter #3: 'test4'

现在看起来相当不错了。但是,在 getopt 命令中仍然隐藏着一个小问题。看看这个例子:

运行:
    [devalone@devalone 14]$ test18.sh -a -b test1 -cd "test2 test3" test4

    found the -a option
    found the -b option, with parameter value 'test1'
    found the -c option
    -d is not an option
    parameter #1: 'test2
    parameter #2: test3'
    parameter #3: 'test4'

getopt 命令并不擅长处理带空格和引号的参数值。它会将空格当作参数分隔符,而不是根据双引号将二者当作一个参数。还有另外一个办法能解决这个问题。

 

● 使用更高级的 getopts
-----------------------------------------------------------------------------------------------------------------------------------------
getopts 命令(注意是复数)内建于 bash shell。它跟近亲 getopt 看起来很像,但多了一些扩展功能。

与 getopt 不同,前者将命令行上选项和参数处理后只生成一个输出,而 getopts 命令能够和已有的 shell 参数变量配合默契。

每次调用它时,它一次只处理命令行上检测到的一个参数。处理完所有的参数后,它会退出并返回一个大于 0 的退出状态码。这让它非常适合用解析命令行
所有参数的循环中。

getopts 命令的格式如下:

    getopts optstring variable

optstring 值类似于 getopt 命令中的那个。有效的选项字母都会列在 optstring 中,如果选项字母要求有个参数值,就加一个冒号。要去掉错误消息的话,
可以在 optstring 之前加一个冒号。getopts 命令将当前参数保存在命令行中定义的 variable 中。

getopts 命令会用到两个环境变量。如果选项需要跟一个参数值,OPTARG 环境变量就会保存这个值。OPTIND 环境变量保存了参数列表中 getopts 正在处理
的参数位置。这样就能在处理完选项之后继续处理其他命令行参数了。

getopts 命令的简单示例:

    [devalone@devalone 14]$ cat test19.sh
    #!/bin/bash
    # simple demonstration of the getopts command
    #
    echo
    while getopts :ab:c opt
    do
        case "$opt" in
            a) echo "Found the -a option";;
            b) echo "Found the -b option, with value $OPTARG";;
            c) echo "Found the -c option";;
            *) echo "Unknown option: $opt";;
        esac
    done

运行:
    [devalone@devalone 14]$ test19.sh -ab test1 -c

    Found the -a option
    Found the -b option, with value test1
    Found the -c option

while语句定义了 getopts 命令,指明了要查找哪些命令行选项,以及每次迭代中存储它们的变量名(opt)。

注意到在本例中case语句的用法有些不同。getopts 命令解析命令行选项时会移除开头的单破折线,所以在 case 定义中不用单破折线。

getopts 命令有几个好用的功能。可以在参数值中包含空格。

运行:
    [devalone@devalone 14]$ test19.sh -ab "test1 test2" -c

    Found the -a option
    Found the -b option, with value test1 test2
    Found the -c option

另一个好用的功能是将选项字母和参数值放在一起使用,而不用加空格。

运行:    
    [devalone@devalone 14]$ test19.sh -abtest1

    Found the -a option
    Found the -b option, with value test1
    
getopts 命令能够从 -b 选项中正确解析出 test1 值。

除此之外,getopts 还能够将命令行上找到的所有未定义的选项统一输出成问号。

运行:
    [devalone@devalone 14]$ test19.sh -d

    Unknown option: ?

    [devalone@devalone 14]$ test19.sh -acde

    Found the -a option
    Found the -c option
    Unknown option: ?
    Unknown option: ?

getopts 命令知道何时停止处理选项,并将参数留给处理。在 getopts 处理每个选项时,它会将 OPTIND 环境变量值增一。在 getopts 完成处理时,
可以使用 shift 命令和 OPTIND 值来移动参数。

示例:

    [devalone@devalone 14]$ cat test20.sh
    #!/bin/bash
    # processing options & parameters with getopts
    #
    echo
    while getopts :ab:cd opt
    do
        case "$opt" in
            a) echo "Found the -a option";;
            b) echo "Found the -b option, with value $OPTARG";;
            c) echo "Found the -c option";;
            d) echo "Found the -d 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

运行:
    [devalone@devalone 14]$ test20.sh -a -b test1 -d test2 test3 test4

    Found the -a option
    Found the -b option, with value test1
    Found the -d option

    Parameter 1: test2
    Parameter 2: test3
    Parameter 3: test4

    
4.5 将选项标准化
-----------------------------------------------------------------------------------------------------------------------------------------
在创建 shell 脚本时,显然可以控制具体怎么做。程序员完全可以决定用哪些字母选项以及它们的用法。但有些字母选项在 Linux 世界里已经拥有了某种
程度的标准含义。如果能在 shell 脚本中支持这些选项,脚本看起来能更友好一些。

下表显示了 Linux 中用到的一些命令行选项的常用含义。

    常用的Linux命令选项
    +-------+---------------------------------------------------------------------------------
    | 选 项    | 描 述
    +-------+---------------------------------------------------------------------------------
    | -a    | 显示所有对象
    +-------+---------------------------------------------------------------------------------
    | -c    | 生成一个计数
    +-------+---------------------------------------------------------------------------------
    | -d    | 指定一个目录
    +-------+---------------------------------------------------------------------------------
    | -e    | 扩展一个对象
    +-------+---------------------------------------------------------------------------------
    | -f    | 指定读入数据的文件
    +-------+---------------------------------------------------------------------------------
    | -h    | 显示命令的帮助信息
    +-------+---------------------------------------------------------------------------------
    | -i    | 忽略文本大小写
    +-------+---------------------------------------------------------------------------------
    | -l    | 产生输出的长格式版本
    +-------+---------------------------------------------------------------------------------
    | -n    | 使用非交互模式(批处理)
    +-------+---------------------------------------------------------------------------------
    | -o    | 将所有输出重定向到的指定的输出文件
    +-------+---------------------------------------------------------------------------------
    | -q    | 以安静模式运行
    +-------+---------------------------------------------------------------------------------
    | -r    | 递归地处理目录和文件
    +-------+---------------------------------------------------------------------------------
    | -s    | 以安静模式运行
    +-------+---------------------------------------------------------------------------------
    | -v    | 生成详细输出
    +-------+---------------------------------------------------------------------------------
    | -x    | 排除某个对象
    +-------+---------------------------------------------------------------------------------
    | -y    | 对所有问题回答yes
    +-------+---------------------------------------------------------------------------------

如果自己的选项也采用同样的含义,这样用户在使用这样的脚本时就不用去查手册了。


4.6 获得用户输入
-----------------------------------------------------------------------------------------------------------------------------------------
尽管命令行选项和参数是从脚本用户处获得输入的一种重要方式,但有时脚本的交互性还需要更强一些。比如想要在脚本运行时问个问题,并等待运行脚本的
用户来回答。bash shell 为此提供了 read 命令。


4.6.1 基本的读取
-----------------------------------------------------------------------------------------------------------------------------------------
read 命令从标准输入(键盘)或另一个文件描述符中接受输入。在收到输入后,read 命令会将数据放进一个变量。下面是 read 命令的最简单用法。

示例:
    [devalone@devalone 14]$ cat test21.sh
    #!/bin/bash
    # testing the read command
    #
    echo -n "Enter your name: "
    read name
    echo "Hello $name, welcome to my program"

运行:
    [devalone@devalone 14]$ test21.sh
    Enter your name: Michael
    Hello Michael, welcome to my program

注意,生成提示的 echo 命令使用了 -n 选项。该选项不会在字符串末尾输出换行符,允许脚本用户紧跟其后输入数据,而不是下一行。这让脚本看起来更
像表单。

实际上,read 命令包含了 -p 选项,允许直接在 read 命令行指定提示符。

示例:
    [devalone@devalone 14]$ cat test22.sh
    #!/bin/bash
    #
    # testing the read -p option
    #
    read -p "Please enter your age: " age
    days=$[ $age * 365 ]
    echo "That makes you over $days days old!"

运行:
    [devalone@devalone 14]$ test22.sh
    Please enter your age: 22
    That makes you over 8030 days old!

再次运行第一个例子,输入名和姓氏两个单词:
    [devalone@devalone 14]$ test21.sh
    Enter your name: Michael Y.
    Hello Michael Y., welcome to my program

在例示例中当有名字输入时,read 命令会将姓和名保存在同一个变量中。read 命令会将提示符后输入的所有数据分配给单个变量,要么就指定多个变量。
输入的每个数据值都会分配给变量列表中的下一个变量。如果变量数量不够,剩下的数据就全部分配给最后一个变量。

示例:
    [devalone@devalone 14]$ cat test23.sh
    #!/bin/bash
    # enter multiple variablse
    #
    read -p "Enter your name: " first last
    echo "Checking data for $last, $first"

运行:
    [devalone@devalone 14]$ test23.sh
    Enter your name: Michael Ya
    Checking data for Ya, Michael

也可以在 read 命令行中不指定变量。如果是这样,read 命令会将它收到的任何数据都放进特殊环境变量 REPLY 中。

示例:
    [devalone@devalone 14]$ cat test24.sh
    #!/bin/bash
    # testing the REPLY environment variable
    #
    read -p "Enter you name: "
    echo
    echo Hello $REPLY, welcome to my program

运行:
    [devalone@devalone 14]$ test24.sh
    Enter you name: Michael

    Hello Michael, welcome to my program

REPLY 环境变量会保存输入的所有数据,可以在 shell 脚本中像其他变量一样使用。


4.6.2 超时
-----------------------------------------------------------------------------------------------------------------------------------------
使用 read 命令时要当心。脚本很可能会一直等着脚本用户的输入。如果不管是否有数据输入,脚本都必须继续执行,可以用 -t 选项来指定一个计时器。
-t 选项指定了 read 命令等待输入的秒数。当计时器过期后,read 命令会返回一个非零退出状态码。

示例:
    [devalone@devalone 14]$ cat test25.sh
    #!/bin/bash
    # enter multiple variablse
    #
    if read -t 5 -p "Enter your name: " name
    then
        echo "Hello $name, welcome to my script"
    else
        echo "Sorry, too slow"
    fi

运行:
    [devalone@devalone 14]$ test25.sh
    Enter your name: Sorry, too slow

如果计时器过期,read 命令会以非零退出状态码退出,可以使用如 if-then 语句或 while 循环这种标准的结构化语句来理清所发生的具体情况。在本例中,
计时器过期时,if 语句不成立,shell 会执行 else 部分的命令。

也可以不对输入过程计时,而是让 read 命令来统计输入的字符数。当输入的字符达到预设的字符数时,就自动退出,将输入的数据赋给变量。

示例:
    [devalone@devalone 14]$ cat test26.sh
    #!/bin/bash
    # getting just one character of input
    #
    read -n1 -p "Do you want to continue [Y/N]?" answer
    case $answer in
        Y | y) echo
               echo "fine, continue on...";;
        N | n) echo
               echo OK, goodbye
               exit;;
    esac
    echo "This is the end of the scripty"

运行:
    [devalone@devalone 14]$ test26.sh
    Do you want to continue [Y/N]?y
    fine, continue on...
    This is the end of the scripty
    [devalone@devalone 14]$ test26.sh
    Do you want to continue [Y/N]?n
    OK, goodbye

本例中将 -n 选项和值 1 一起使用,告诉 read 命令在接受单个字符后退出。只要按下单个字符回答后,read 命令就会接受输入并将它传给变量,无需按
回车键。


4.6.3 隐藏方式读取
-----------------------------------------------------------------------------------------------------------------------------------------
有时需要从脚本用户处得到输入,但又在屏幕上显示输入信息。其中典型的例子就是输入的密码,但除此之外还有很多其他需要隐藏的数据类型。

-s 选项可以避免在 read 命令中输入的数据出现在显示器上。

示例:
    [devalone@devalone 14]$ cat test27.sh
    #!/bin/bash
    # hiding input data from the monitor
    #
    read -s -p "Enter your password: " pass
    echo
    echo "Is your password really $pass ?"

运行:
    [devalone@devalone 14]$ test27.sh
    Enter your password:
    Is your password really 12345 ?

输入提示符输入的数据不会出现在屏幕上,但会赋给变量,以便在脚本中使用。


4.6.4 从文件中读取
-----------------------------------------------------------------------------------------------------------------------------------------
也可以用 read命令来读取 Linux 统上文件里保存的数据。每次调用 read 命令,它都会从文件中读取一行文本。当文件中再没有内容时,read 命令会退出
并返回非零退出状态码。

其中最难的部分是将文件中的数据传给 read 命令。最常见的方法是对文件使用 cat 命令,将结果通过管道直接传给含有 read 命令的 while 命令。

示例:
    [devalone@devalone 14]$ cat test28.sh
    #!/bin/bash
    # reading data from a file
    #
    count=1
    cat test | while read line
    do
        echo "Line $count: $line"
        count=$[ $count + 1 ]
    done

    echo "finished processing the file"

运行:
    [devalone@devalone 14]$ cat test
    The quick brown dog jumps over the lazy fox.
    This is a test, this only a test.
    Romeo,Romeo! wherefore art thou Romeo?

    [devalone@devalone 14]$ test28.sh
    Line 1: The quick brown dog jumps over the lazy fox.
    Line 2: This is a test, this only a test.
    Line 3: Romeo,Romeo! wherefore art thou Romeo?
    finished processing the file


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

 

系列目录:

    Linux shell 脚本编程-基础篇 (一)

    Linux shell 脚本编程-基础篇 (二)

    Linux shell 脚本编程-基础篇 (三)

    Linux shell 脚本编程-基础篇 (四)

    Linux shell 脚本编程-基础篇 (五)

    Linux shell 脚本编程-基础篇 (六)

 

-----------------------------------------------------------------------------------------------------------------------------------------


参考:

    《Linux 命令行与 shell 脚本编程大全》 第 3 版 —— 2016.8(美)Richard Blum  Cristine Bresnahan

Shell脚本编程基础及实战 本文还有配套的精品资源,点击获取 简介:标题和简介未提供具体信息,但通过标签“Shell”推测主题与Unix/Linux系统中的Shell脚本编程相关。Shell是命令行解释器,允许执行系统操作。Shell脚本用于自动化命令行任务,包含控制结构、条件语句、循环语句等。本课程深入探讨Shell编程基础,包括脚本结构、变量赋值、命令行参数处理、流程控制、文件与目录操作、管道与重... 阅读详情

相关推荐

Angular 相关的知识点和项目汇总

Angular 知识点和项目汇总

weixin_45428910的博客 581

【shell实战之】处理选项_查找选项_处理含值的选项

【代码】【shell实战之】处理选项_查找选项_处理含值的选项。

m0_61126667的博客 110

ZEMAX学习第7天-手机镜头光学系统设计全过程案例

接下来对系统微调,依次缩小CRA和畸变,首先对CRA进行依次递减(39°、38°、37°、36°、35°),目前CRA角度40度,每次下降一度进行优化,利用MAXX加OPLT一起控制,控制小于35°。可以看出在标注的三个地方镜头曲率变化,导致PY=1的光线走向奇特,因此需要对矢高进行调整,按照标注的地方依次调整(从右到左)至传函变好,越靠近右边对其余视场影响越小。3.圆锥系数值较大,透镜形状怪异;一、第1,3镜子偏厚,第4镜子偏薄,45镜子间隔边缘偏小,第5片镜子中心厚度与边缘厚度相差较大,需要控制;

liningliwei的博客 1085

linux脚本中option,linux新手关于shell脚本一个小问题,请教各位高手

问题一:这是一个在脚本中使用getopt命令格式化为脚本输入任意命令行选项或参数的问题代码如下:#!/bin/bashset--'getopt-qab:c"$@"'while[-n"$1"]docase"$1"in-a)echo"Foundthe-aoption";;-b)param="$2"echo"Foundthe-boption,withpara...

weixin_42338883的博客 232

孤读paper——《GhostNet:More Features from Cheap Operations》

《GhostNet:More Features from Cheap Operations》   发现一个点并解决就是一篇CVPR,该文章主要发现了优秀的网络的特点是feature map提取过程中的冗余性,这种冗余性体现在很多成对的feature map间很像,就好像彼此的“ghost”,而这种特征冗余性对于理解图像来说还是必要的,所以文章把feature map分为两种,一种是本质特征,一...

雄关漫道真如铁 而今迈步从头越 5151

网格自适应_Comsol案例解析17:自适应网格的使用

本期导读自适应网格细化有许多优势,比如可以不用对网格进行全局加密,增加计算精度,又会降低求解自由度。本期仍然以气泡上升案例为例,在两相流模块中使用自适应网格。【打开案例模型】【修改网格】适当让气泡边界加密,注意,曲率因子越小,曲线上的网格越密【添加自适应网格】使用默认的参数即可,这里的误差指示器用的是水平集phi。可以根据具体求解模型选择适当的自变量作为误差指示器。【口诀】默认的一般是最...

weixin_28726871的博客 5682

shell处理用户输入——特殊参数变量

在bash shell中有一些跟踪命令行参数的特殊变量。

2401_82591819的博客 644

基于Simulink的直流电机双闭环调速系统抗扰动仿真与参数优化

本文详细介绍了基于Simulink的直流电机双闭环调速系统仿真与参数优化方法。通过构建转速外环与电流内环的仿真模型,阐述了利用工程设计法整定PI参数的核心步骤,并重点探讨了如何优化系统参数以增强其抗负载突变等扰动的能力,实现快速、平稳的调速性能。

weixin_29061997的博客 195

shell读书笔记8

18、处理用户输入 18.1、命令行参数 18.1.1、读取参数 位置参数变量是标准的数字:$0是程序名,$1是第一个参数,$2是第二个参数,依次类推,直到第九个参数$9 I、下面是在shell脚本中使用单个命令行参数的简单例子。 $ cat test1.sh #!/bin/bash # using one command line parameter # factorial=1 for (( number = 1; number <= 1;number++))dofactorial=1 ; numb

a777122的博客 195

【项目实战】SOVD协议(面向服务的车辆诊断协议)

此外,AUTOSAR组织将SOVD部分内容的软件实现定义在了R22-11及以上版本的AUTOSAR Adaptive规范中,还支持动态发现车内诊断功能、获取高性能计算机(HPC)的Log信息等新的诊断需求,更符合当前软件定义汽车概念下的行业趋势。而SOVDGateway作为边缘节点,也肩负着对SOVD Client进行认证以及权限控制的责任,从而保证车辆的信息安全。相较于传统的UDS(Unified Diagnostic Services)协议,SOVD不仅保留了传统的读写数据、例程控制、故障读取等功能,

奶爸的编程之路,也就一周冷个三天 1905

SAR图像降噪:基于小波变换和双边滤波器的Matlab实现

小波变换和双边滤波器是常用的图像降噪技术,它们可以在保持图像细节的同时有效抑制噪声。本文介绍了基于小波变换和双边滤波器的SAR图像降噪方法,并提供了相应的Matlab源代码。通过对比原始图像和降噪后的图像,可以观察到噪声得到一定程度的抑制,同时保留了图像的细节信息。本文将介绍一种基于小波变换和双边滤波器的方法,用于SAR图像的降噪,并提供相应的Matlab源代码。希望这篇文章能够帮助您理解基于小波变换和双边滤波器的SAR图像降噪方法,并为您提供实现该方法的Matlab源代码。对图像的高频部分进行降噪处理。

ScriptCharm的博客 841

【Linux】基础篇四--shell脚本编程

Linux学习4--shell脚本编程一、shell编程-变量1、shell脚本的基础知识2、shell变量二、shell编程-功能语句1、说明性语句2、常用功能性语句3、测试语句三、shell编程-分支语句1、条件语句2、多路分支语句四、shell编程-循环语句1、循环语句for的用法2、循环语句while的用法3、循环控制语句五、shell编程-函数1、shell函数调用2、函数变量作用域 一、shell编程-变量 1、shell脚本的基础知识 (1)shell脚本的本质 程序语言包括编译型语言与解释型

修成真的博客 8168

[AI工具评测] 为什么功能全面的 Kimi Claw,最终还是被放弃?

《KimiClaw:功能整合与体验落差的AI工具实践》 KimiClaw作为集LLM、Agent、云端执行和SaaS分发于一体的AI工具,理论上具备个人开发者所需的全栈能力:原生整合大模型与Agent、支持云端Docker部署、可生成Web应用并通过飞书协作。然而实际高频使用中暴露三大核心问题:响应延迟导致思考节奏断裂(非流式输出)、云端黑箱执行缺乏可控性(无法实时干预)、系统稳定性不足(网关和隧道偶发故障)。这些体验落差表明,功能完整性不等于使用高效性——对开发者而言,实时响应、执行透明度和系统可靠性比自

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 536

Linux shell 脚本编程-高级篇 (四)

继 Linux shell 脚本编程-高级篇 (三)   4. 正则表达式 在 shell 脚本中成功运用 sed 编辑器和 gawk 程序的关键在于熟练使用正则表达式。这可不是件简单的事,从大量数据中过滤出特定数据可能会(而且经常会)很复杂。 4.1 什么是正则表达式 4.1.1 定义 正则表达式是所定义的模式模板(pattern template),Linux 工具可以用它来...

devalone 的专栏 1397

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Linux Shell 脚本编程基础知识篇—shell简介以及基本操作

Shell本身是一个用C语言编写的程序, 它是用户使用Linux的桥梁。Shell既是一种命令语言, 又是一种程序设计语言。所有的Linux命令都是Shell脚本语言。

weixin_55767624的博客 2723

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Linux基础命令-SHELL脚本编程基础

Linux基础命令-SHELL脚本编程基础SHELL脚本编程基础一、编程基础1. 编程基础2. 程序的执行方式3. 编译和解释型语言4. 编程基本概念二、脚本基本格式1. shell脚本基础2. 创建shell脚本3. 脚本规范4. 编程基本概念5. shell脚本示例6. 脚本调试三、变量1. 变量2. bash中变量的种类a. 局部变量b. 环境变量c. 只读和位置变量3. 退出状态4. 退出...

qq_41596208的博客 1604

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Linux 编写shell 脚本基础篇

LInux shell编程基础 sh bash dash区别 执行脚本方式 变量的使用 字符串

xxx_un的博客 2271

linux-Shell 编程-Shell 脚本基础

Shell脚本是由一系列Linux命令组成的文本文件,通常用于自动化完成任务。Shell脚本可以在终端中运行,而无需逐个输入命令。Shell脚本的扩展名通常为.sh,但这不是强制性的。在Shell脚本中,变量的使用是非常灵活的。变量名必须以字母或下划线开头,不能以数字开头。定义变量引用变量在引用变量时,需要在变量名前加上# 函数体Shell脚本是Linux系统管理中不可或缺的工具。通过Shell编程,用户可以自动化处理系统任务、文件操作、网络操作等一系列功能。

Flying_Fish_roe的博客 1698

Linux基础_SHELL脚本编程基础

讲师_@王晓春 本章内容▼编程基础▼shell脚本基础▷创建shell脚本▷脚本的基本结构▷变量1. Shell中变量命名法则:2. bash中变量的种类局部变量环境变量位置变量退出状态3. 算术运算赋值逻辑运算4. test命令bash的数值测试bash的文件测试54. 使用read命令来接受输入6. 条件选择 if 语句7. 条件判断:case语句▼bash的配置文件▷编辑配置文件生效1. B...

Not Found 404 3948

SHELL 脚本编程基础

文章目录1. shell 概述1.1 shell 和 shell 脚本1.2 Shell 脚本应用场景1.4 shell 类型 1. shell 概述 1.1 shell 和 shell 脚本   shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务,在用户和内核之间充当翻译官的角色,是一个命令解释器。Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面 shell。   shell 脚本(

shenyuanhaojie的博客 3万+

Linux Shell 脚本编程基础知识篇—shell 运算命令详解

各位好,我是练小杰,本文继续Linux shell脚本编程的基础知识内容,接着讲算术运算命令的详细操作,主要是led命令,read命令,be命令,expr命令等。

weixin_55767624的博客 1738

shell 编程基础

shell编程基础

qq_67582098的博客 1883

shell脚本编程基础

Linux的Shell种类众多,常见的有:/bin/sh /bin/bash /sbin/nologin /bin/dash /bin/tcsh /bin/csh  从程序员的角度来看, Shell本身是一种用C语言编写的程序,从用户的角度来看,Shell是用户与Linux操作系统沟通的桥梁。用户既可以输入命令执行,又可以利用 Shell脚本编程,完成更加复杂的操作。在Linux GUI日益完善的今

Wyxtnbp的博客 2730

Linux Shell 脚本编程

shell本质上就是用户与计算机交互的界面/窗口。用户将要执行的操作通过shell传递给计算机,计算机将执行的结果通过shell返回给客户端。用户执行操作的方法Ⅰ:用户通过鼠标点击完成发送要执行的操作指令Ⅱ:用户直接发送命令shell分类图形化shell:GUI例:winodws桌面字符化shell:CLI例:linux的shell窗口位置参数,也被称之为位置变量通过位置参数,可以在执行程序的时候,向程序传递数据shell接收参数的方法向shell传递参数的方法。

m0_65544268的博客 2753

Linux基础之初识SHELL脚本

Shell脚本(Shell Script )可以简单理解为多个LINUX命令的堆砌,与Windows/Dos下的批处理相似

高飞的博客 31万+

linux之基础shell脚本编程1 基础变量赋值

linux之基础shell脚本编程1 基础变量赋值

第九系艾文 3036
上一篇: Linux shell 脚本编程-基础篇 (三)
下一篇: Linux shell 脚本编程-基础篇 (五)
devalone
博客等级 码龄17年 108粉丝 80原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值