shell脚本编程
注意 本人的博客都迁移到本人自己搭建的博客地址,通过此处可查看。
构建基本脚本
注释格式
#!/bin/sh
# FILENAME: test_shell
# AUTHOR: Javy
# Email: xujavy@gmail.com
# PURPOSE: Demonstration of comment style
# HISTORY: 1 May, 2018 Created
# 5 May, 2018 Modified to show mods
显示消息
echo This is a test
说明:
- -n:输出在同一行
使用变量
1. 环境变量
- set 显示所有的当前环境变量列表
例如:
#!bin/bash
# display user information from the system.
echo "User info for userid: $USER"
echo UID: $UID
echo HOME: $HOME
2. 用户变量
3. 命令替换
-
反引号字符( `)
-
$()格式
#!bin/bash
testing=$(date)
重定向输入和输出
1. 输出重定向
command > outputfile
2. 输入重定向
command < outputfile
管道
执行数学运算
1. expr命令
expr 1 + 5
2. 使用方括号
$[ operation ]
3. 浮点解决方案
- bc的基本用法
bc -q
quit
2. 在脚本中使用bc
variable=$(echo "options; expression" | bc)
说明:
options:设置变量,允许多个变量可以用分号隔开。
expression:定义bc执行的数学表达式。
variable=$(bc << EOF options statements expression EOF )
退出脚本
1. 查看退出状态码
$?
可查看退出状态
说明:
状态码 | 描述 |
---|---|
0 | 命令成功结束 |
1 | 一般性未知错误 |
2 | 不适合的shell执行命令 |
126 | 命令不可执行 |
127 | 没找到命令 |
128 | 无效的退出参数 |
128+x | 与Linux信息x相关的严重错误 |
130 | 通过Ctrl+C终止的命令 |
255 | 正常范围之外的退出状态码 |
2. exit命令
可以指定退出码exit num
,num表示0~255之间的数,如果大于将以取模的形式返回。
使用结构化命令
使用if-then语句
格式:
if command then
commands
fi
说明:
if后面的command是一个命令,如果命令退出代码是0,then部分就会被允许,如果是其他码then部分不会被执行。
使用if-then-else语句
格式:
if command then
commands
else
commands
fi
嵌套if
test命令
test condition
if test condition then
commands
fi
也可以写为:
if [ condition ] then
commands
fi
test命令可以判断的三类条件:
-
数值比较
-
字符串比较
-
文件比较
1. 数值比较
比较 | 描述 | 比较命令说明 |
---|---|---|
n1 -eq n2 | n1是否与n2相等 | -equal |
n1 -ge n2 | n1是否大于或等于n2 | -(greater and equal) |
n1 -gt n2 | n1是否大于n2 | -(greater than) |
n1 -le n2 | n1是否小于或等于n2 | -(less and equal) |
n1 -lt n2 | n1是否小于n2 | -(less than) |
n1 -ne n2 | n1是否不等于n2 | -(not equal) |
2. 字符串比较
比较 | 描述 |
---|---|
str1 = str2 | str1是否与str2相同 |
str1 != str2 | str1是否与str2不同 |
str1 < str2 | str1是否比str2小 |
str1 > str2 | str1是否比str2大 |
-n str1 | str1的长度是否非0 |
-z str1 | str1的长度是否为0 |
注: 在使用<
和>
是需要进行转义,就想这样\<
和\>
。
3. 文件比较
比较 | 描述 |
---|---|
-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新 |
file1 -ot file2 | file1是否比file2旧 |
复合条件测试
-
[ condition1 ] && [ condition2 ]
-
[ condition1 ] || [ condition2 ]
if-then的高级特性
-
用于数学表达式的双括号
-
用于高级字符串处理功能的双方括号
1. 使用双括号
格式:
(( expression ))
表达式参数符号说明:
符号 | 描述 |
---|---|
val++ | 后增 |
val– | 后减 |
++val | 先增 |
–val | 先减 |
! | 逻辑求反 |
~ | 位求反 |
** | 幂运算 |
<< | 左位移 |
>> | 右位移 |
& | 位布尔和 |
| | 位布尔或 |
&& | 逻辑和 |
|| | 逻辑或 |
2. 使用双方括号
[[ expression ]]
case命令
格式:
case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) default commands;;
esac
更多的结构化命令
for命令
格式:
for var in list
do
commands
done
C语言风格的for命令
格式:
for (( variable assignment ; condition ; iteration process ))
使用多个变量:
for (( a=1, b=10; a <= 10; a++, b-- )); do
#statements
done
while命令
格式:
while [ command ]
do
other commands
done
until命令
格式:
until [ command ]
do
other commands
done
嵌套循环
循环处理文件数据
控制循环
1. break命令
跳出外部循环:break n (默认n=1)
2. continue命令
处理循环的输出
for (( i = 0; i < 10; i++ )); do
#statements
done > outputfile.txt
最后的结果使用定向输出:>
处理用户输入
命令行参数
1. 读取参数
位置参数变量是标准的数字:$0是程序名,$1是第一个参数,$2是第二个参数,依次类推直到第九个参数$9。
2. 抓取所有的数据
$*
和$@
可以抓取命令行上的所有参数。但是$*
是当作一个参数执行,而$@
是对每个参数进行处理
3. 移动变量
shift 2
:移动两个位置
4. 处理选项
分离参数和选项(--
)
使用getopt
命令:getopt optstring parameters,在脚本中使用格式:set –
(
g
e
t
o
p
t
−
q
a
b
:
c
d
"
(getopt -q ab:cd "
(getopt−qab:cd"@")
使用更高级的getopts
:getopt optstring variable
4. 获得用户输入
read
echo -n "Enter your name: "
read name
echo "Hello $name, welcome to my program. "
read -p
read -p "Enter your age: " age
days=$[ $age * 365 ]
echo "That makes you over $days days old! "
2. 超时
read -t
if read -t 5 -p "Please Enter your name: " name
then
echo "Hello $name, welcome to my program. "
else
echo
echo "Sorry, too slow!"
fi
read -n1
read -n1 -p "Do you want to continue [Y/N]?: " answer
case $answer in
Y | y) echo
echo "fine, continue on...";;
N | n) echo
echo "Ok, goodbye"
exit;;
esac
echo "This is the end of the script"
3. 隐藏方式读取
read -s
read -s "Enter your password: " pass
echo
echo "Is your password really $pass? "
4. 从文件中读取
Count=1
cat test | while read line
do
echo "Line $Count: $Line"
Count=$[ $Count + 1 ]
done
echo "Finished processing the file"
呈现数据
理解输入和输出
1. 标准文件描述符
文件描述符 | 缩写 | 描述 |
---|---|---|
0 | STDIN | 标准输入 |
1 | STDOUT | 标准输出 |
2 | STDERR | 标准错误 |
2. 重定向错误
ls -al test 2> test1 1> test2
ls -al test &>test1
在脚本中重定向输出
1. 临时重定向
2. 永久重定向
exec 1>testout
echo "...."
echo "......."
在脚本中重定向输入
exec 0< testfile
创建自己的重定向
1. 关闭文件描述符
exec 3>&-
列出打的开文件描述符
lsof
记录消息
tee filename 默认会覆盖
tee -a filename 实现追加
实例
#!bin/bash
# read file and create INSERT statements for MySQL
outputfile='member.sql'
IFS=','
while read lname fname address city state zip
do
cat \>> $outputfile \<< EOF
INSEART INTO members (lname, fname, address, city, state, zip) VALUES ('$lname', '$fname', '$address', '$city', '$state', '$zip');
EOF
done < S{1}
控制脚本
处理信号
1. 重温Linux信号
信号 | 值 | 描述 |
---|---|---|
1 | SIGHUP | 挂起进程 |
2 | SIGINT | 终止进程 |
3 | SIGQUIT | 停止进程 |
9 | SIGKILL | 无条件终止进程 |
15 | SIGTRERM | 尽可能终止进程 |
17 | SIGSTOP | 无条件停止进程但不是终止进程 |
18 | SIGTSTP | 停止或暂停进程,但不终止进程 |
19 | SIGCONT | 继续运行停止的进程 |
2. 生成信号
- 中断进程
Ctrl + C
- 暂停进程
Ctrl + Z
3. 捕获信号
格式:
tarp commands signals
4. 捕获脚本退出
tarp commands signals EXIT
5. 修改或移除捕获
以后台模式运行脚本
1. 以后台运行脚本
./test.sh &
2. 运行多个后台作业
在非控制台下运行脚本
格式:
nohup ./test.sh &
作业控制
1. 查看作业
jobs
参数说明:
参数 | 描述 |
---|---|
-l | 列出进程的PID以及作业号 |
-n | 只列出上次shell发出的通知后改变了状态的作业 |
-p | 只列出作业的PID |
-r | 只列出运行中的作业 |
-s | 只列出已停止的作业 |
2. 重启停止的作业
后台模式运行:bg id
前台模式运行:fg id
调整谦让度
1. nice命令
nice -n:指定新的优先级级别
2. renice命令
renice -n 10 -p 5055
定时运行作业
1. 用at命令来计划执行作业
- at命令的格式
格式:
at [ -f filename ] time
at -f test.sh now
- 列出等待的作业
atq可以查看系统中等待的作业
- 删除作业
arrm删除等待的作业
2. 安排需要定期执行的脚本
- cron时间表
格式:
min hour dayofmonth month dayofweek command
- 构建cron时间表
crontb -l:列出时间表
- 浏览cron目录
包括:hourly、daily、monthly、weekly
ls /etc/cron.*ly
- anacron程序
格式:
period delay identifier command
高级shell脚本编程
创建函数
基本的脚本函数
1. 创建函数
function name {
commands
}
name() {
commands
}
2. 使用函数
返回值
- 默认退出状态码
$?
- 使用return命令
注意: 函数一结束就取返回值;退出状态码必须是0~255。
- 使用函数输出
在函数中使用变量
局部变量:local temp
数组变量和函数
图形化桌面环境中的脚本编程
初识sed和gawk
文本处理
1. sed编辑器
sed:stream editor
说明:
-
一次从输入中读取一行数据
-
根据所提供的编辑器命令匹配数据
-
按照命令修改流中的数据
-
将新的数据输出到STDOUT。
格式:
sed options script file
选项:
选项 | 描述 |
---|---|
-e script | 在处理输入时,将script中指定的命令添加到已有的命令中 |
-f file | 在处理输入时,将file中指定的命令添加到已有的命令中 |
-n | 不产生命令输出,使用print命令完成输出 |
- 格式:
sed ‘s/test/big test/’
例如:
echo “this is a test” | sed ‘s/test/big test/’
sed ‘s/dog/cat/’ data.txt
- 执行多个命令格式:
sed -e ‘e/brown/green/;s/dog/cat/’ data.txt
- 从文件中读取编辑器命令
sed -f file.sed data.txt
2. gawk程序
- gawk命令格式
gawk options program file
可用选项:
选项 | 描述 |
---|---|
-F fs | 指定行中划分数据字段的字段分隔符 |
-f file | 从指定的文件中读取程序 |
-v var=value | 定义gawk程序中的一个变量及其默认值 |
-mf N | 指定要处理的数据文件中的最大字段数 |
-mr N | 指定数据文件中的最大数据行数 |
-W keyword | 指定gawk的兼容模式或警告等级 |
- 从命令行读取程序脚本
graw ‘{print “Hello World!”}’
- 使用数据字段变量
$0:代表整个文本行
$1:代表文本行中的第1个数据字段
$2:代表文本行中的第2个数据字段
$n:代表文本行中的第n个数据字段
sde编辑器基础
1. 更多的替换选项
- 替换标记
s/pattern/replacement/flags
flags:
-
数字:将新文本替换第几行模式匹配的地方
-
g:替换所有
-
p:原先行的内容要打印出来
-
w:file,将替换的结果写到文件中
- 替换字符
/
2. 使用地址
行寻址(line addressing)
-
以数字形式表示行区间
-
用文本模式来过滤出行
格式:
[address] command
address{
command1
command2
command3
}
- 数字方式的行寻址
sed ‘2s/dog/cat’ data.txt
sed ‘2,3s/dog/cat’ data.txt
sed ‘2,$s/dog/cat’ data.txt
- 使用文本模式过滤器
格式:
/pattern/command
- 命令组合
3. 删除行
sed ‘d’ data.txt
4. 插入和附加文本
- insert命令i
- append命令a
格式:
sed ‘[address]command\new line’
举例:
sed ‘i\Test line 1’
sed ‘a\test line 1’
5. 修改行
sed ‘3c\t xxxx’ data.txt
转换命令
[address]y/inchars/outchars