shell command-line arguments (base)

Command line parameters

\ $ 0 for the program name.
\ $ 1 \ $ 9 is the location parameter.
\ $ # Is the number of parameters.
\ $ * All parameters as a whole to refer to
\ $ @ to return each parameter as a string, you can use a for loop to iterate over
\ $? Exit status of the most recent command executed. 0 indicates a successful execution
\ $ _ last argument on a command. Use the shortcut keys ESC +. This effect is

Positional parameters

More than nine positional parameters, more parameters is the same support. Only to use \ $ {10} such forms reference.
\ $ 1 and \ $ {1} effect is the same.
Without braces, then \ $ 10 would be considered a \ $ 1 and a 0 character.

Parameter values with spaces
of each parameter is separated by spaces. To include a space in the parameter value must be in quotation marks (single or double quotes available).

When the parameters are passed as a text string, the quotation marks are not part of the data. They simply indicate the start and end position data.

Get the script name

\ $ 0 for the script name, but the result of different calls returned by the method is different. The following script is a simple print \ $ 0 value:

$ cat filename.sh 
#!/bin/bash
echo $0
$ ./ filename.sh
-bash: ./: 是一个目录
$ cat filename.sh 
#!/bin/bash
echo $0
$ ./filename.sh
./filename.sh
$ bash filename.sh 
filename.sh
$ bash /root/filename.sh 
/root/filename.sh
$ 

Use basename command
if you want to use the name of the script to be judged, you can use the command basename path information to filter out. The effect of the command is as follows:

$ basename /var/log/messages 
messages
$ 

Therefore, the above script can be modified in such a way:

$ cat filename.sh 
#!/bin/bash
echo $(basename $0)
$ ./filename.sh
filename.sh
$ bash filename.sh 
filename.sh
$ bash /root/filename.sh 
filename.sh
$ 

Test parameters

Using parameters in the script to ensure that the parameters exist, or they may runtime error:

$ cat add.sh 
#!/bin/bash
echo $1 + $2 = $[ $1 + $2 ]
$ ./add.sh 1 2
1 + 2 = 3
$ ./add.sh 1
./add.sh:行2: 1 +  : 语法错误: 期待操作数 (错误符号是 "+  ")
$ 

If only as a reference to the string, not an error. The Senate did not pass the default parameters are empty:

$ cat hello.sh 
#!/bin/bash
echo Hello $1 $2.
$ ./hello.sh Tom Jerry
Hello Tom Jerry.
$ ./hello.sh Jerry
Hello Jerry .
$ ./hello.sh
Hello .
$ 

Determining whether there is a parameter
determined non-empty string, then the -Z contrary, air is truth -n use in the shell. Above has been tested, undefined parameter is empty by default:

$ cat hello.sh 
#!/bin/bash
if [ -n "$1" ]
then
    echo Hello $1.
else
    echo Hello Nobody.
fi
$ ./hello.sh Tom
Hello Tom.
$ ./hello.sh
Hello Nobody.
$ 

Here's judgment \ $ 1 to be in quotes, otherwise it will be considered as a string. Of course, a non-empty string, the result will always be true.

Determining the number of parameters of
the above example can also script determines the number of parameters is larger than 0 to realize:

$ cat hello.sh 
#!/bin/bash
echo 参数数量: $#
if [ $# -gt 0 ]
then
    echo Hello $1.
else
    echo Hello Nobody.
fi
$ ./hello.sh
参数数量: 0
Hello Nobody.
$ ./hello.sh Tom
参数数量: 1
Hello Tom.
$ ./hello.sh Tom Jerry
参数数量: 2
Hello Tom.
$ 

Here -gt compared before and after the two numbers (INT), so \ $ # is not quoted.
This method can also be determined by whether or not the parameter is present. Both methods, the same effect, different books have seen someone use.

Here is an example of the same addition, it must pass two parameters:

$ cat add.sh 
#!/bin/bash
if [ $# -eq 2 ]
then
    echo $1 + $2 = $[ $1 + $2 ]
else
    echo 需要参数: 2, 实际参数: $#.
fi
$ ./add.sh 1 2
1 + 2 = 3
$ ./add.sh 1 2 3
需要参数: 2, 实际参数: 3.
$ ./add.sh 1
需要参数: 2, 实际参数: 1.
$ 

If you want to represent not equal, that is, if [ $# -ne 2 ]

Gets the last parameter
which is a use \ $ # tips. Use ${$#}seems to be the last one of the variable parameters.
But it is not true, curly braces can not do this with \ $, here should be replaced inside the exclamation point:

$ cat hello.sh 
#!/bin/bash
if [ $# -gt 0 ]
then
    echo Hello ${!#}.
else
    echo Hello Nobody.
fi
$ ./hello.sh Tom Jerry
Hello Jerry.
$ 

If no command-line arguments, it is the return \ $ 0, which is the name of the script.

Exclamation mark above problem, the effect is the reference variable value instead of the variable itself. Similar to the value of the pointer. The number # replaced with the name of a variable to explain more intuitive:

$ cat parameter.sh 
#!/bin/bash
paramater=key
key=value
echo "${paramater}"
echo "${!paramater}"
echo "${key}"
$ ./parameter.sh 
key
value
value
$ 

Without an exclamation point, it is to go directly to the value of the variable. Exclamation point, is to go to the variable value of that variable corresponding to the variable name.

Get all parameters

\ $ * And \ $ @ are represented all the strings, but there will be differences at the time of traversal:

$ cat all.sh 
#!/bin/bash
echo '$* 的效果:'
count=1
for i in "$*"
do
    echo $count: $i
    count=$[ $count + 1 ]
done
echo '$@ 的效果:'
count=1
for i in "$@"
do
    echo $count: $i
    count=$[ $count + 1 ]
done
$ ./all.sh Oliver Barry Kara Sara Kane
$* 的效果:
1: Oliver Barry Kara Sara Kane
$@ 的效果:
1: Oliver
2: Barry
3: Kara
4: Sara
5: Kane
$ 

\ $ * On a whole value, you can not traverse. To traverse each variable you want to use \ $ @. Here the double quotes is very important.

Without quotes, then, it is the \ $ * and \ $ @ content (after multivariate analysis is more than one word) passed to the for loop iterates, the effect of such two parameters are the same. And the string does not pass directly quoted the same effect.
With quotes, quotes of content is a whole. If it is \ $ *, as a whole in all this is a word, not demolition. If it is \ $ @, press the space bar this whole there will be split into multiple words.
Here is the demonstration effect:

$ cat all2.sh 
#!/bin/bash
echo '$* 不加引号的效果:'
count=1
for i in $*
do
    echo $count: $i
    count=$[ $count + 1 ]
done
echo '$@ 不加引号的效果:'
count=1
for i in $@
do
    echo $count: $i
    count=$[ $count + 1 ]
done
echo '直接遍历不加引号的字符的效果:'
count=1
for i in Oliver Barry Kara Sara Kane
do
    echo $count: $i
    count=$[ $count + 1 ]
done
echo '加引号遍历的效果:'
count=1
for i in "Oliver Barry Kara Sara Kane"
do
    echo $count: $i
    count=$[ $count + 1 ]
done
$ ./all2.sh Oliver Barry Kara Sara Kane
$* 不加引号的效果:
1: Oliver
2: Barry
3: Kara
4: Sara
5: Kane
$@ 不加引号的效果:
1: Oliver
2: Barry
3: Kara
4: Sara
5: Kane
直接遍历不加引号的字符的效果:
1: Oliver
2: Barry
3: Kara
4: Sara
5: Kane
加引号遍历的效果:
1: Oliver Barry Kara Sara Kane
$ 

Stressed: Special Parameters \ $ @ must use in double quotes, each parameter effect is extended to separate words. When using a for loop iterates will reflect the results.

Mobile variable shift

The shift command can be used to operate the command line parameters. By default, each parameter one position to the left. The removed parameter is discarded, and can not be restored.
First master the use of this command, use this command can easily parse command line arguments.

Examples of Use

The following is a simple example:

$ cat pop.sh 
#!/bin/bash
count=1
while [ -n "$1" ]
# while [ $# -ne 0 ]
do
    echo "$count: $1"
    count=$[ $count + 1 ]
    shift
done
$ ./pop.sh Oliver Barry Kara Sara Kane
1: Oliver
2: Barry
3: Kara
4: Sara
5: Kane
$ 

There are two methods of determining parameter to determine whether there is, the effect is the same.

Moving a plurality of positions

Executed with no parameters shift, specify the location you want to move a few will be able to:

$ cat pop.sh 
#!/bin/bash
count=1
# while [ -n "$1" ]
while [ $# -ne 0 ]
do
    if [ -n "$2" ]
    then
        echo "$count: $1, $2"
        shift 2
    else
        echo "$count: $1"
        shift
    fi
    count=$[ $count + 1 ]
done
$ ./pop.sh Oliver Barry Kara Sara Kane
1: Oliver, Barry
2: Kara, Sara
3: Kane
$ 

Simple modifications script above, a two output parameters, and then moved two positions.

Processing Options

When the shell script requires multiple command-line parameters when calling the script must all parameters fixed order.
Or you can also use the option to specify the value of the parameter.

case with shift

This case there is an option with a value also has the option without a value:

$ cat format.sh 
#!/bin/bash
prefix=""    # 前缀
base="test"  # 默认字符串
suffix=""    # 后缀
upper=off    # 是否大写
# 解析命令行参数
while [ -n "$1" ]
do
    case "$1" in
        -a) suffix="$2"
            shift ;;
        -b) prefix="$2"
            shift ;;
        -s) base="$2"
            shift ;;
        -u) upper=on ;;
         *) echo "$1 is not an option"
            exit 1 ;;  # 发现未知参数,直接退出
    esac
    shift
done
# 添加前缀和后缀
output="${prefix:+${prefix}_}${base}${suffix:+_${suffix}}"
# 判断是否要全大写输出
if [ $upper = on ]
then
    output=${output^^}
fi
# 输出结果
echo "$output"
$ ./format.sh -a after
test_after
$ ./format.sh -s hello -b befor
befor_hello
$ ./format.sh -s hello -u -a after -b befor
BEFOR_HELLO_AFTER
$ ./format.sh -s hello -u -a after -b befor -l
-l is not an option
$ 

case statement to find an option to deal with an option. If you provide the required parameters on the command line, it can be handled in the case of general processing section. And here there is no need to provide any parameters, any incorrect parsing errors on the report and exit (exit 1).

Parameter version can resolve
this version match all the parameters of output format:

$ cat format.sh 
#!/bin/bash
prefix=""    # 前缀
base="test"  # 默认字符串
suffix=""    # 后缀
upper=off    # 是否大写
# 显示声明一下这是个数组变量,其实没有必要
declare -a names  # 需要格式化输出的所有原始字符串
# 解析命令行参数
while [ -n "$1" ]
do
    case "$1" in
        -a) suffix="$2"
            shift ;;
        -b) prefix="$2"
            shift ;;
        -s) base="$2"
            shift ;;
        -u) upper=on ;;
         *) names=("${names[@]}" "$1") ;;
    esac
    shift
done
names[0]=${names[0]:-$base}
for name in "${names[@]}"
do
    # 添加前缀和后缀
    output="${prefix:+${prefix}_}${name}${suffix:+_${suffix}}"
    # 判断是否要全大写输出
    if [ $upper = on ]
    then
        output=${output^^}
    fi
    # 输出结果
    echo "$output"
done
$ 
$ ./format.sh -a after -b befor -u value1 value2 value3
BEFOR_VALUE1_AFTER
BEFOR_VALUE2_AFTER
BEFOR_VALUE3_AFTER
$ ./format.sh -a after after1 -b befor befor1 -u value1 value2 value3
BEFOR_AFTER1_AFTER
BEFOR_BEFOR1_AFTER
BEFOR_VALUE1_AFTER
BEFOR_VALUE2_AFTER
BEFOR_VALUE3_AFTER
$ ./format.sh -a after after1 -b befor befor1 -u -v value1 value2 value3
BEFOR_AFTER1_AFTER
BEFOR_BEFOR1_AFTER
BEFOR_-V_AFTER
BEFOR_VALUE1_AFTER
BEFOR_VALUE2_AFTER
BEFOR_VALUE3_AFTER
$ 

See the results of the last two, the command-line parameters provided there is a problem, but the program can not be found.
The penultimate item can be considered supplied argument is correct, but the options and parameters alternately.
The last item provides a bad option, but can not be identified.
To solve this problem, we need to be more disciplined approach to separate parameters and options. The contents of the next section.

Array problem with spaces
add to the array elements There are many ways, this is a re-creation of an array of practices:

array_name=("${array_name[@]}" value1 ... valueN)

You can add several elements, if the string contains spaces, it is necessary quotation marks.

And command-line arguments \ $ @ and \ $ * Like, all the array elements have two similar symbols. The most rigorous method is to use "${names[@]}"the @ double quotes.
Add elements and remove the element of time should pay attention to, otherwise there is the element with spaces when it will destroy the original array elements are separated.
Add an element used here:

names=("${names[@]}" "$1")

Not only is the array of elements, the elements must be added in quotes, or if there is space, according to multiple elements will be added to the array.

Use traverse the elements:

for name in "${names[@]}"

When only add correctly in order to correct traversal. Then traverse the time but also to ensure correct.
Verify the effect of:

$ ./format.sh -a after -b befor -u value1 "value2 value3" value4
BEFOR_VALUE1_AFTER
BEFOR_VALUE2 VALUE3_AFTER
BEFOR_VALUE4_AFTER
$ 

perfect.

Separating parameters and options

The argument here is that in addition to the parameters defined options, other additional command-line parameters. Juggling parameters and options, you must use special characters (double-dashed line -) to separate the two. Double-dashed line indicates the end of the list of options, double break behind the broken line are parameters. Based on this logic, as long as the judge in the case plus a statement on the line.
The above script to make some changes:

$ cat format.sh 
#!/bin/bash
prefix=""    # 前缀
base="test"  # 默认字符串
suffix=""    # 后缀
upper=off    # 是否大写
# 显示声明一下这是个数组变量,其实没有必要
declare -a names  # 需要格式化输出的所有原始字符串
# 解析选项
while [ -n "$1" ]
do
    case "$1" in
        -a) suffix="$2"
            shift ;;
        -b) prefix="$2"
            shift ;;
        -s) base="$2"
            shift ;;
        -u) upper=on ;;
        --) shift
            break ;;
         *) echo "$1 is not an option"
            exit 1 ;;  # 发现未知参数,直接退出
    esac
    shift
done
# 解析参数
while [ -n "$1" ]
do
    names=("${names[@]}" "$1")
    shift
done
names[0]=${names[0]:-$base}
for name in "${names[@]}"
do
    # 添加前缀和后缀
    output="${prefix:+${prefix}_}${name}${suffix:+_${suffix}}"
    # 判断是否要全大写输出
    if [ $upper = on ]
    then
        output=${output^^}
    fi
    # 输出结果
    echo "$output"
done
$ 

For this version, when in use, you need to enter an item, then double-dashed line separated, then the input parameters. When the script encounters double-dashed line, it will stop processing options, and the rest of the argument as parameters:

$ ./format.sh -a after -b befor -u value1 value2 value3
value1 is not an option
$ ./format.sh -a after -b befor -u -- value1 value2 value3
BEFOR_VALUE1_AFTER
BEFOR_VALUE2_AFTER
BEFOR_VALUE3_AFTER
$ ./format.sh -a after -b befor -v -u -- value1 value2 value3
-v is not an option
$ 

For the first time do not use dual-dashed line, so the error.
The second separated the correct parameters and options with a double dash.
Third appearance undefined options In the Options section, can be found errors.

Summary
content of this section is also laying the groundwork for the following getopt command. getopt that can help us to complete parse command line arguments, returns a list of parameters separated by regular options and parameters of double broken lines.
Also here does not support the merge options:

$ ls -al

These problems can be solved with getopt, but also support long options.

Guess you like

Origin blog.51cto.com/steed/2443313