shell脚本移位优于重新分配值的优势很明显

时间:2018-04-11 14:22:06

标签: bash

我不理解以下代码中的shift

    #! /usr/local/bin/bash
    # process command line options
    interactive=
    filename=
    while [[ -n $1 ]]; do
        case $1 in 
            -f | --file)    shift #don't understand the shift #No.1
                            filename=$1 ;;
            -i | --interactive) interactive=1
                                ;;
            -h | --help)    usage
                            exit;;
            *)              echo "usage >&2 exit 1";;
        esac
        shift # don't understand the shift #2
    done

    #interactive mode
    if [[ -n $interactive ]]; then
       echo "do something"
    fi
    #output html page
    if [[ -n $filename ]]; then
        if touch $filename && [[ -f $filename ]]; then
           echo "write_html_page > $filename" #debug 
        else
            echo "$program: Cannot write file $filename " >&2
            exit 1
        fi
    else
        echo "write_html_page to terminal" # debug
    fi

测试

    $ bash question.sh -f test
    write_html_page > test

    $ bash question.sh -f
    write_html_page to terminal

当我删除shift并将filename=$1更改为filename=$2

    $ bash question.sh -f
    write_html_page to terminal
  # it works properly

    $ bash question.sh -f test
    usage >&2 exit 1
    write_html_page > test 
  # it almost function  nicely except that `usage >&2 exit 1` is executed.

因此shift无法完全替换为filename=$2

如果删除了第二次转移,循环就会无休止地运行。

我可以直观地解释shift吗? 我没有用其他语言找到这样一个神奇的命令。

2 个答案:

答案 0 :(得分:2)

此页面上的示例:

  

http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_07.html

解释了它在做什么。

编辑:

示例:

  

当事先不知道命令的参数个数时,通常使用shift语句,例如,当用户可以根据需要提供尽可能多的参数时。在这种情况下,参数通常在while循环中处理,测试条件为(($#))。只要参数的数量大于零,这种情况就成立了。 $ 1变量和shift语句处理每个参数。每次执行移位时参数的数量都会减少,最终变为零,while循环退出。

答案 1 :(得分:2)

shift将删除第一个位置参数,并将每个其他参数左移一个。

例如,让我们考虑以下事项:

#!/bin/bash
echo "$@"
shift
echo "$@"
shift
echo "$@"

鉴于echo "$@"将打印所有参数,如果您要运行此参数,则会发生以下情况:

./test.bash 1 2 3 4 5

echo "$@"  # prints 1 2 3 4 5
shift      # Removes 1 and shifts everything else along
echo "$@"  # prints 2 3 4 5
shift      # shifting again
echo "$@"  # prints 3 4 5

在您的示例中,脚本正在解析所有标志。 -i-h只是开关,不处理以下参数。但是,-f需要filename

第二个shift将处理标志,移动参数,然后再次处理它们。因此,您可以拥有./program.bash -i -f filename-i将在第二个班次移动,然后文件名将在下一个循环中处理。

如果您要运行./program.bash -f filename -i,则filename需要与-f一起移动。因此,在-f的案例块上有一个额外的转移。在此示例中,-f将在大小写块内移动,然后filename将移动第二个shift。然后循环将再次运行以处理任何进一步的标志。

由于while循环是[[ -n $1 ]],循环将一直运行,直到没有其他参数。