shell脚本编程基础

参考《Linux 命令行与shell脚本编程大全》

1. 构建基本脚本

将多个shell命令放到shell脚本文件中。

1.1 shell脚本文件

第一步:创建文件

vim test

第二步:写shell脚本

#!/bin/bash
# this is a comment!
date
who
#...

第三步:赋予执行文件权限

$ chmod u+x test

第四步:运行脚本

$ ./test

1.2 基本命令

命令作用规则示例
echo显示消息单引号或双引号将文本字符串圈起来echo "hello world !"
$variable使用变量(环境变量、用户变量)变量、等号、值之间不能出现空格,shell脚本自动决定变量类型name="peter" echo $name
反引号(`)将shell命令的输出赋给变量testing=`date`
> >> < <<重定向输入输出
管道(|)将一个命令的输出重定向到另一个command1 | command2 在第一个命令产生输出的同时,输出会被立即送给第二个命令,传输数据不会用到任何中间文件或缓冲区。
expr命令允许在命令行上处理数学表达式$ expr 1+5 $ 6
方括号($[ ])数学运算$[operatrion]var=$[1+5]
bash计算器bc允许浮点表达式运算内建,bc开始,quit退出
exit命令退出脚本返回退出状态码,linux提供$?专属变量保存上个执行命令的退出状态码exit 0

2. 使用结构化命令(条件)

2.1 if-then语句

if语句先运行if行定义的那个命令,如果该命令的退出状态码是0(表示命令运行成功),then部分的命令就会被执行,否则不执行。格式如下:

if command
then
    commands
fi

2.2 if-then-else命令

if command
then
    commands
else
    commands
fi

2.3 嵌套if

if command
then
    commands
elif command
then
    commands
fi

2.2 test命令

如果test命令中列出的条件成立,test就会退出并且返回退出状态码0;如果条件不成立,返回1。

test conditon

和if-then语句配合使用

if test conditon
then
    commands
fi

bash shell 提供另外一种在if-then语句中声明test命令的方法:

if [condition]
then
    commands
fi

test命令可以判断3类条件:
1. 数值比较
2. 字符串比较
3. 文件比较

2.3 复合条件测试

两种布尔运算符
1. AND: [condition1] && [condition2]
2. OR: `[condition1] || [conditon2]

2.4 case命令

case命令为变量每隔可能的值指定不同的选项。

case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) default_commands;;
esac

3. 更多的结构化命令(循环)

循环命令:for/while/until

3.1 for

基本格式:

#list 可以是①直接写出的列表②变量③从命令读取值(需要反引号) `cat $file`
for var in list
do
    commands
done

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

3.2 更改字段分隔符

内部字段分隔符 IFS(internal field separator, 一个特殊的环境变量),IFS定义了bash shell 用作字段分隔符的一系列字符:空格、制表符、换行符。

例如,输出文件中的每行

IFS=$'\n'
for line in `cat file.txt`
do
    echo $line
done

3.3 用通配符读取目录下的文件

输出当前目录下的所有文件:

bash> echo ./*

shell脚本:

#!/bin/bash
#print file in dir

#也可以列出一系列的目录通配符
#for file in ./* /Home/Documents/*
for file in ./* 
do
    if [ -d "$file" ]
    then
        echo "$file is a directory"
    elif [ -f "$file" ]
    then
        echo "$file is a file"
    fi
done

exit 0

3.4 C语言风格的for命令

格式:

for (( variable1 assignment, variable2 assignment; conditon; iteration process ))
do
    commands
done

例如1+2+3+…+10

sum=0
for (( i=1;i<=10;i++))
do
    sum=$[$sum+$i]
done
echo $sum
#结果输出55

3.4 while命令

格式:

while test command
do
    commands
done

3.5 until命令

和while命令完全相反
格式:

until test command
do
    commands
done

3.6 控制循环

  1. break命令
  2. continue命令

3.7 重定向循环的输出

格式

for var in list
do
    commands
done > output.txt

4. 处理用户输入

4.1 命令行参数

位置参数:特殊变量,分配给命令行输入的所有参数:$0是脚本的整个路径,使用basename $0来获取程序名,$1是第一个参数,$2直到第9个参数$9, 如果多于9个命令行参数,则在数字周围加花括号,${10}, ${11}…

basename命令:输入完整路径,返回程序名。例如:

$ basename /home/documents/test.txt
test.txt

测试参数:当脚本以为参数变量中会有数据,而实际并没有时,脚本会得到一个错误消息。在使用数据前检查数据确实已经存在于变量中。

#!/bin/bash
#cmd parameter

echo $0
name=`basename $0`
echo $name

if [ -n "$1" ]
then
    echo $1
fi

exit 0

4.2 特殊参数变量

(1)命令行参数个数

$#特殊变量,含有命令行参数的个数,对程序名不计数。 可以和普通变量一样使用。

echo "there are $# paremeters"

使用if-then语句用test命令行提供的参数总数执行数值测试,如果参数总是不对,可以打印一条错误消息说明脚本的正确用法。

(2)命令行参数

$*变量,将命令行上提供的所有参数当作单个单词保存。
$@变量,将命令行上提供的所有参数当作字符串保存。可以使用for命令遍历所有的值。

IFS='\n'
for para in $@
do
    echo $para
done

4.3 移动变量

4.4 处理选项

(1)使用getopt命令:接受一系列任意形式的命令行选项和参数,并自动转换成适当的格式。

getopt optstring options parameters

(2)使用getopts命令

4.5 获得用户输入(read命令)

read命令:接受从标准输入(键盘)或文件描述符的输入,并将数据放在一个或多个变量中。

read命令选项作用示例
-p允许直接在read命令行指定提示符read -p "please enter your name: " name
-t指定read命令等待输入的秒数read -t 5 var
-s隐藏读取的数据(用于密码等)read -s -p "please enter your code: " code

从文件中读取数据,最常见的方法:将文件运行cat命令后的输出通过管道直接传给含有read命令的while命令,例如

#!/bin/bash
#read from file

cnt=0
cat input.file | while read line
do
    cnt=$[$cnt+1]
    echo "line $cnt is: $line"
done

exit 0

5. 呈现数据

1. 标准文件描述符

bash shell 保留了最早的3个文件描述符(0、1、2)

文件描述符缩写描述
0SIDIN标准输入
1STDOUT标准输出
2STDERR标准错误

2. 重定向

默认情况下,linux会将STDERR定向到STDOUT.

重定向标准输出:

cat inputfile 1> outfile

重定向标准错误:

cat not_exist_file 2> errfile

重定向数据和错误1:

cat inputfile not_exist_file 1> outfile 2> errfile

重定向数据和错误2:使用特殊的重定向符号&>

cat inputfile not_exist_file &>err_out_file

3. 在脚本中重定向输出

3.1 临时重定向每行输出

在重定向到文件描述符时,必须在文件描述符数字之前加一个and符号(&)
这个方法非常适合在脚本中生成错误消息。

#!/bin/bash
#chong ding xiang

#将这行输出重定向到“错误输出”
echo "this is an err msg" >&2

#将这行输出重定向到指定文件
echo "this is a normal output to file" > out_file

#正常输出
echo "this is a normal output"

exit 0

运行时,指定文件描述符重定向的位置(文件),例如: ./bashfile 2> errfile

3.2 永久重定向脚本中的所有命令

exec命令:告诉shell脚本在运行期间,重定向某个特定文件描述符。

#!/bin/bash
#chong ding xiang

#将标准输出重定向到指定文件
exec 1> stdoutfile

echo "this is a normal output"

exit 0

4. 在脚本中重定向输入

exec 0< input_file
#之后,当使用read命令时,则直接重input_file中读取

5. 创建自己的重定向

在shell中最多可以有9个打开的文件描述符。

5.1 创建输出文件描述符

exec 3>out3_file

echo "this should be stored in the file" >&3

5.2 重定向文件描述符

5.3 创建输入文件描述符

在重定向到文件之前,先将STDIN文件描述符保存到另外一个文件描述符,然后在读取完文件之后将STDIN恢复到它原来的位置

#保存
exec 6<&0

#重定向
exec 0<input_file

#do something
#...

#恢复
exec 0<&6

5.4 创建读写文件描述符

在向同一个文件进行读写数据操作,shell维护一个内部指针,指明现在在文件中的位置,任何读写都会从文件指针上次保存的位置开始。

exec 3<> in_and_out_file

echo "this is a line" >&3
read line <&3
echo $line

5.5 关闭文件描述符

  1. shell会在脚本退出时,自动关闭。
  2. 当需要在shell退出前关闭文件描述符,需要手动exec 3>$-

6. 列出打开的文件描述符

lsof命令:输出整个linux系统打开的所有文件描述符。

选项含义
-p指定进程ID
-d指定要显示的文件描述符个数
-a对其他两个选项的结果执行布尔AND运算

7. 阻止命令输出

当脚本作为后台进程执行时,不想显示脚本的输出。
阻止任何数据或错误消息而不保存它们的一个通用方法:将STDOUT或STDERR重定向到/dev/null文件(特殊文件,null文件的任何数据都不会保存)。

./shellfile > /dev/null

8. 临时文件

/tmp目录:linux系统留给临时文件的特殊目录位置,在系统启动时自动删除/tmp目录的所有文件。
mktemp命令:在本地目录中创建一个临时文件,返回创建临时文件的全路径。

mktemp tempfile.XXXXXX

在脚本中使用mktemp命令时,将文件名保存到变量中,在后面的脚本中引用。
创建临时目录,需要使用-d选项

mktemp -d dir.XXXXXX

9. 记录消息(tee命令)

tee – read from standard input and write to standard output and files

6. 控制脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值