后浪笔记一零二四

1. 分支语句

① 使用if-then语句

1
2
3
4
if command
then
    commands
fi

注意,和c语言不同,bash shell的if语句会运行if后面的那个命令。如果该命令的退出状态码是0,位于then部分的命令就会被执行。如果该命令的退出状态码是其他值,then部分的命令就不会被执行,bash shell会继续执行脚本中下一个命令。fi语句用来表示if-then语句到此结束。

② test命令 如果test命令中列出的条件成立,test命令就会退出并返回退出状态码0。如果条件不成立,test命令就会退出并返回非零的退出状态码。 bash shell还提供了另一种条件测试方法,使用[]替代test命令。

1
2
3
4
if [ condition ] # 第一个方括号之后和第二个方括号之前必须加上一个空格。
then
    commands
fi

test命令可以判断三类条件:数值比较,字符串比较,文件比较。注意,test中不能使用浮点数

test命令的数值比较功能

比较 描述
n1 -eq n2 检查n1是否与n2相等
n1 -ge n2 检查n1是否大于或等于n2
n1 -gt n2 检查n1是否大于n2
n1 -le n2 检查n1是否小于或等于n2
n1 -lt n2 检查n1是否小于n2
n1 -ne n2 检查n1是否不等于n2

test命令的字符串比较功能

比较 描述
str1 = str2 检查str1是否和str2相同
str1 != str2 检查str1是否和str2不同
str1 \< str2 检查str1是否比str2小,脚本会把<和>看做重定向符号,所以需要转义
str1 \> str2 检查str1是否比str2大
-n str1 检查str1的长度是否非0
-z str1 检查str1的长度是否为0

注意,在进行字符串比较的时候,test命令处理大写字母的方法刚好和sort命令相反。在test中,大写字母被认为是小于小写字母的。test使用的是标准的ASCII顺序,根据每个字符的ASCII数值来决定排序结果。sort命令使用的是系统的本地化语言设置中定义的排序顺序。对于英文,本地化设置指定了在排序顺序中小写字母出现在大写字母前。

test命令的文件比较功能

比较 描述
-b file file is a block device
-d file 检查file是否存在并是一个目录
-e file 检查file是否存在
-f file 检查file是否存在并是一个文件
-r file 检查file是否存在并可读
-s file 检查file是否存在并非空
-w file 检查file是否存在并可写
-x file 检查file是否存在并可执行
-O file 检查file是否存在并属当前用户所有
-G file 检查file是否存在并且默认组与当前用户相同
file1 -nt file2 检查file1是否比file2新
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
device0="/dev/sda2"   # /   (root directory)
# -b表示块设备
if [ -b "$device0" ]
then
  echo "$device0 is a block device."
fi

device1="/dev/tty$1"   # PCMCIA modem card
# -c表示字符设备
if [ -c "$device1" ]
then
  echo "$device1 is a character device."
fi

function show_input_type()
{
    # -p表示管道
    [ -p /dev/fd/0 ] && echo PIPE || echo STDIN
}
show_input_type "Input"
echo "Input" | show_input_type

复合条件测试

1
2
与: [ condition1 ] && [ condition2 ]
或: [ condition1 ] || [condition2]

-a logical and exp1 -a exp2 returns true if both exp1 and exp2 are true.

-o logical or exp1 -o exp2 return true if either exp1 or exp2 is true.

There are similar to the Bash comparison operators && and || , used within double brackets. [[ condition1 && condition2 ]]

The -o and -a operators work with the test command or occur within single test brackets.

1
2
3
4
5
6
if [ "$expr1" -a "$expr2" ]
then
  echo "Both expr1 and expr2 are true."
else 
  echo "Either expr2 or expr2 is false."
fi

In a compound test, even quoting the string variable might not suffice(不够) . [ -n “$string” -o “$a” = “$b” ] may cause an error with some versions of Bash if $string is empty. The safe way is to append an extra character to possibly empty variables, [ “x$string” != x -o “x$a” = “x$b” ]

2. case命令

1
2
3
4
5
case variable in
pattern1 | pattern2) command1;;
pattern3) command2;;
*) default command;;
esac

3. 循环命令

3.1 for命令

1
2
3
4
for var in list
do 
    commands
done

$test变量保持了其值,也允许我们修改它的值,并在for循环之外跟其他变量一样使用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
$ cat test1b
#!/bin/bash
# testing the or variable after the looping

for test in Alabama Alaska Arizona Arkansas California Colorado
do 
    echo "The next state is $test"
done
echo "The last state we visited was $test"
test=Connecticut
echo "Wait, now we're visiting $test"
$ ./test1b
The next state is Alabama
The next state is Alaska
The next state is Arizona
The next state is Arkansas
The next state is California
The next state is Colorado
The last state we visited was Colorado
Wait, now we're visiting Connecticut

shell看到了列表值中的单引号并尝试使用它们来定义一个单独的数据值,这真是把事情搞得一团糟。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$ cat badtest1
#!/bin/bash
# another example of how not to use the for command

for test in I don't konw if this'll work
do 
    echo "word:$test"
done
$ ./badtest1
word:I
word:dont know if thisll
word:work

有两种办法可以解决这个问题:使用转义字符(反斜线)来将单引号转义,使用双引号来定义用到单引号的值。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ cat test2
#!/bin/bash
# another example of how not to use the for command

for test in I don\'t konw if "this'll" work
do 
    echo "word:$test"
done
$ ./test2
word:I
word:don't
word:konw
word:if
word:this'll
word:work

for循环假定每个值都是用空格分割的。如果有包含空格的数据值,就必须用双引号将这些值圈起来。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
$ cat test3
#!/bin/bash
# an example of how to properly define values

for test in Nevada "New Hampshire" "New Mexico" "New York"
do 
    echo "Now going to $test"
done
$ ./test3
Now going to Nevada
Now going to New Hampshire
Now going to New Mexico
New goint to New York

有个特殊的环境变量IFS(internal field separator内部字段分隔符)。IFS环境变量定义了bash shell用作字段分割符的一系列字符。默认情况下,bash shell会将下列字段当做字段分割符:空格,制表符,换行符。(在for命令中会这样做)

用通配符读取目录中的所有文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
$ cat test6
#!/bin/bash
# interate through all the files in a directory

for file in /home/rich/test/*
do
    if [ -d "file" ] #在linux中,目录名和文件名中包含空格当然是合法的。要适应这种情况,应该将$file变量用双引号圈起来。如果不这么做,遇到含有空格的目录名或文件名时就会有错误产生。
    then
        echo "$file is a directory"
    elif [ -f "$file" ]
    then 
        echo "$file is a file"
    fi
done

3.2 C语言风格的for命令

for (( variable assignment; condition; iteration process ))注意,这种for命令,迭代器的算式没有使用expr命令,也没有使用$[operation]。

1
2
3
4
for (( i=1; i <= 10; i++))
do 
    echo "The next number is $i"
done

跳出外部循环

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$ cat test20
#!/bin/bash
# breaking out of an outer loop

for (( a = 1; a < 4; a++))
do 
    echo "Outer loop: $a"
    for (( b = 1; b < 100; b++))
    do
        if [ $b -gt 4 ]
        then
            break 2 #跳出两层循环,跳出本循环直接break
        fi
        echo "    Inner loop: $b"
    done
done

continue的用法和break一样,只是它是直接进入下次循环的入口判断。

3.3 while命令

1
2
3
4
while test command
do
    other command
done

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ cat test10
#!/bin/bash
# while command test

var1=10
while [ $var1 -gt 0 ]
do
    echo $var1
    var1=$[ $var1 - 1 ]
done

3.4 until命令

1
2
3
4
until test commands
do
    other commands
done

3.5 实例 列出PATH目录下所有的命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$ cat test25
#!/bin/bash
# finding files in the PATH

IPS=:
for folder in $PATH
do 
    echo "$folder:"
    for file in $folder/*
    do
        if [ -x $file ]
        then
            echo "    $file"
        fi
    done
done

创建多个用户账户

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# read命令会自动读取.csv文本文件的下一行内容,所以不需要专门再写一个循环来处理。当read命令返回FLASE时(也就是读取完整个文件时),while命令就会退出。
$ cat test26
#!/bin/bash
# process new user accounts

input="users.csv"
while IFS=',' read -r userid name
do
    echo "adding $userid"
    useradd -c "$name" -m $userid
done < "$input"

$ cat users.csv
rich,Richard Blum
christine,Christine Bresnahan
barbara,Barbara Blum
tim,Timothy Bresnahan

本文发表于 0001-01-01,最后修改于 0001-01-01。

本站永久域名「 jiavvc.top 」,也可搜索「 后浪笔记一零二四 」找到我。


上一篇 « 下一篇 »

赞赏支持

请我吃鸡腿 =^_^=

i ysf

云闪付

i wechat

微信

推荐阅读

Big Image