Linux Shell脚本编程

将Linux命令组合成一个文本文件,在须要运行这些命令时,只用运行这个文本即可

创建文件

在shell脚本文件的第一行指定要使用的shell: #!/bin/bash

在通常的shell脚本中,#用作注释行,shell不会处理脚本中的注释行,除了第一行。#后面的!告诉系统用哪个shell解释器

例如,在命令行中输入vim test.sh

#!/bin/bash
date
who

上述脚本等价于date;who,使用了;将命令组合并按顺序执行

保存文件并退出vim,注意此时在命令行里输入./test.sh,并不能直接运行:

$ ./test.sh
bash: ./test.sh: Permission denied

因为没有执行权限:

$ ls -l test.sh
-rw-rw-r-- 1 hwx hwx 21 Sep  1 11:34 test.sh

使用chmod修改权限后运行:

$ chmod u+x test.sh
$ ./test.sh 
Thu 01 Sep 2022 11:43:55 AM CST
root      :0           2022-09-01 08:45 (:0)

使用变量

通过变量可以临时性的将信息存储在shell脚本中

环境变量

shell维护着一组环境变量,用来记录特定的系统信息。比如系统的名称、登录到系统上的用户名、用户的系统ID(也叫UID)、用户默认的主目录以及shell查找程序的搜索路径,可以用set命令来显示一份完整的当前变量列表:

$ set
BASH=/usr/bin/bash
BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore:globasciiranges:histappend:interactive_comments:progcomp:promptvars:sourcepath
BASH_ALIASES=()
....

使用美元符号加变量名可以使用这些环境变量,编写如下shell脚本:

#!/bin/bash
echo "User info for userid: $USER"
echo UID: $UID
echo HOME: $HOME

运行输出:

$ ./test.sh 
User info for userid: hwx
UID: 1000
HOME: /home/hwx

echo命令中的环境变量会在脚本运行时替换成当前的值,放在双引号中同样起作用,所以要显示美元符得用\转义

用户变量

除了环境变量,shell脚本还允许定义和使用自己的变量,临时存储数据并在整个脚本中使用,使用等号将值赋给用户变量,变量、等号和值之间不能有空格

#!/bin/bash
var1=10
var2=-20
var3=test
var4="just a test"

引用一个变量时需要美元符,但引用变量来赋值时不使用美元符号

 #!/bin/bash
value1=10
value2=$value1
echo $value2

value2=value1
echo $value2

运行:

$ ./test.sh 
10
value1

使用$才能将value1的值赋值给value2,否则只是一个字符串

命令替换

有时要从命令输出中提取信息,并将其赋值给变量,把输出赋给变量后就可以随意在脚本中使用,使用反引号或$()可以从命令中提取提示信息:

 #!/bin/bash
test=$(date)
echo "The date and time are: " $test 

等价于:

 #!/bin/bash
echo "The date and time are: " `date`

重定向输入输出

将命令的输出重定向到另一个位置(比如文件,而非显示器),也可以用于输入

输出重定向

最基本的重定向将命令的输出发送到一个文件中,bash shell用大于号(>)来完成这个功能:command > outputfile

输出到标准输出的命令输出就会被保存到指定的输出文件中,如下所示:

$ date > test.txt
$ cat test.txt 
Thu 01 Sep 2022 02:43:53 PM CST

重定向操作符创建了一个文件(默认的权限掩码),并将date命令的输出重定向到该文件中。若文件已经存在,则会将原有的覆盖,使用>>便不会覆盖,而是追加数据

$ date >> test.txt
$ cat test.txt 
Thu 01 Sep 2022 02:43:53 PM CST
Thu 01 Sep 2022 02:47:26 PM CST

输入重定向

输入重定向是将文件的内容重定向到命令,而非将命令输出重定向到文件,输入重定向符号是小于号(<): command < inputfile

$ wc < test.txt
 2 14 64

wc命令的作用是对文本文件进行计数,默认输出: 行数 词数 字节数

通过将文本文件重定向到wc命令,立刻就可以得到文件中的行、词和字节的计数

另外还有内联输入重定向,这种方法不需要使用文件进行重定向,只需在命令行中指定用于输入重定向,使用远小于号(<<),同时必须指定一个文本标记来划分输入数据的开始和结尾:

$ wc << EOF
> Hello
> World
> EOF
 2  2 12

管道

将一个命令的输出作为另一个命令的输入,这可以用重定向来实现,也可以用管道: command1 | command2

在进程中匹配含有http的进程:

$ ps -af | grep http
hwx        25820   21362  0 15:36 pts/2    00:00:00 grep --color=auto http

ps -af输出的进程列表被输入给grep http

结构化命令

许多程序要求对shell脚本中的命令施加一些逻辑流程控制

if-then语句

最基本的结构化命令,格式如下:

if command
then
	commands
fi

bash shell的if语句会运行if后面的命令,如果该命令的退出码是0,则位于then部分的命令就会被执行,其他情况下就不会执行then部分,fi表示到此结束

如下一段代码所示:

#!/bin/bash
if pwd
then
    echo "It worked"
fi

运行:

$ ./test.sh
/home/hwx
It worked

如果pwd命令成功结束则返回0,echo语句就会显示该文本字符串

如下if后是一条不存在的命令:

#!/bin/bash
if UnknowCommand
then
    echo "It worked"
fi
echo "finish"

运行:

$ ./test.sh 
./test.sh: line 2: UnknowCommand: command not found
finish

then没有被运行

if-then-else语句

如果命令遇到一个非0退出码,让bash shell继续执行脚本中的另一组命令便可借助这个命令

示例:

#!/bin/bash
testuser=NoSuchUser
if grep $testuser /etc/passwd
then
    echo "The bash files for user $testuser are:"
    ls -a /home/$testuser/.b*
    echo
else
    echo "The user $testuser does not exist on this system"
    echo
fi

运行:

$ ./test.sh 
The user NoSuchUser does not exist on this system

指定的用户名并不存在,所以得到一个非0退出,相应的就执行else语句

嵌套if语句

if语句可以嵌套使用,如下所示:

#!/bin/bash
testuser=NoSuchUser
if grep $testuser /etc/passwd
then
    echo "The bash files for user $testuser are:"
    ls -a /home/$testuser/.b*
    echo
else
    echo "The user $testuser does not exist on this system"
    if ls -d /home/$test
    then
        echo "However, $testuser has a dictory."
    fi
fi

运行:

$ ./test.sh 
The user NoSuchUser does not exist on this system
ls: cannot access '/home/NoSuchUser': No such file or directory

这段程序通过查看/etc/passwd检查是否存在某个用户名,之后通过ls -d检查该用户的目录是否存在

可以将elif语句串起来,形成一个if-elif嵌套组合:

#!/bin/bash
testuser=NoSuchUser
if grep $testuser /etc/passwd
then
    echo "The bash files for user $testuser are:"
elif ls -d /home/testuser
then 
    echo "the user $testuser does not exist on this system"
    echo "However, $testuser has a dictory"
else
    echo "The user $testuser does not exist on this system"
    echo "However, $testuser has a dictory"
fi

运行:

$ ./test.sh 
ls: cannot access '/home/testuser': No such file or directory
The user NoSuchUser does not exist on this system
However, NoSuchUser does not have a dictory

要注意的是,elif语句中,紧跟其后的else语句属于elif代码块,并不属于之前的if-then代码

test命令

test命令中列出的条件如果成立,test命令就会退出并返回状态码0: test condition

与if-then配合使用:

if test condition
then
	commands
fi

示例:

#!/bin/bash
value="test"
if test $value
then
    echo "True"
else
    echo "False"
fi    

还有一种与test相同的语句,用于条件测试:

if [ conditions ]
then
	commands
fi

方括号中定义了测试条件,第一个方括号之后和第二个方括号之前必须加上一个空格

#!/bin/bash
v1=10
v2=11
if [ $v1 -gt 5 ]
then
    echo "The test value $v1 is greater than 5"
fi
if [ $v1 -eq $v2 ]
then
    echo "The value are equal"
else
    echo "The value are different"
fi

运行:

$ ./test.sh 
The test value 10 is greater than 5
The value are different
posted @ 2022-09-09 09:27  N3ptune  阅读(90)  评论(0编辑  收藏  举报