目录
shell编程
shell 关键字
1. echo
2. exec
3. read
4. expr
5. let
6. test
7. “<<”
三 Shell程序中的选择结构
1. if-then控制结构
2. case-esac控制结构
四 Shell程序中的循环结构
1. for
2. while
3. break、continue
4. while read line
五 函数和数组的使用
六 shell实现数据库的批量插入
七 shell调试
1、创建方法:用vi编辑器创建 如:vi hello.sh
2、编辑脚本文件需要注意的内容:第一行以“#!”开头,声明所使用的shell的全路径,如:#!/bin/bash
3、赋予可执行权限:chmod +x hello.sh 执行:./hello.sh
常用的关键字如下:
输出打印文字到屏幕
echo两个常用的参数:-e 识别输出内容里的转译字符;-n 忽略结尾的换行
[root@node673 test]# echo "hello\tworld"
hello\tworld
[root@node673 test]# echo -e "hello\tworld"
hello world
[root@node673 test]# echo -e -n "hello\tworld"
hello world[root@node673 test]#
执行另一个 shell脚本
#!/bin/bash
exec ./hello.sh
读取标准输入
read常用参数:-p 添加提示信息
#!/bin/bash
read -p "please enter a word: " testvar
echo "you entered $testvar"
运行脚本:
[root@node673 test]# ./test_read.sh
please enter a word: test
you entered test
对整数型变量进行算术运算,也可以进行字符串的相关运算
①. 对整数型变量进行算术运算:
使用方法:expr 表达式1 操作符 表达式2
乘法操作符" * "前面必须要用' \ '用来转译。每个表达式和操作符之间必须有空格(这一点与let不同)
#!/bin/bash
i=10
j=20
k=6
res1=`expr $i + $j + $k`
res2=`expr $i - $j - $k`
res3=`expr $i \* $j \* $k`
res4=`expr $i \* $j / $k`
echo $res1
echo $res2
echo $res3
echo $res4
运行脚本:
[root@node673 test]# ./practice_expr.sh
i+j+k=36
i-j-k=-16
i*j*k=1200
# 整除结果只能保存为整数
i*j/k=33
②. 对字符串进行算术运算:
#!/bin/bash
str1="abcdefg"
# 输出字符串长度
l1=`expr length $str1`
# 使用echo输出字符串长度
l11=`echo ${#str1}`
# 截取字符串子串
l2=`expr substr $str1 1 3` #expr截取时,下标是从1计算
# 使用echo截取字符串子串
l22=`echo ${str1:0:3}` #echo截取时,下标是从0计算
# 字符串连接
str2="12345"
str3="${str1}$str2"
echo $l1
echo $l11
echo $l2
echo $l22
echo $str3
运行脚本:
[root@node673 test]# ./practice_expr_str.sh
7
7
abc
abc
abcdefg12345
只执行整数的相关运算,运算结果也只能保存整数
使用方法:let 变量名 = 变量1 运算符 变量2
#!/bin/bash
i=10
j=20
k=6
let res1="$i+$j+$k"
let res2="$i-$j-$k"
let res3="$i*$j*$k"
let res4="$i*$j/$k"
echo "i+j+k=$res1"
echo "i-j-k=$res2"
echo "i*j*k=$res3"
echo "i*j/k=$res4"
运行脚本:
[root@node673 test]# ./practice_let.sh
i+j+k=36
i-j-k=-16
i*j*k=1200
# 整除结果只能保存到整数
i*j/k=33
对两个值进行比较,比较成功返回0,否则返回非0
常用的比较方法:
使用方法:test value1 -option value2
如果成功则返回0($?为0),否则返回非0,常用于判断操作。
test整数比较的方法:
大于 | gt |
小于 | lt |
大于等于 | ge |
小于等于 | le |
等于 | eq |
不等于 | ne |
举个栗子:
#!/bin/bash
a=1
b=2
c=2
d=4
echo -e "a:$a\t b:$b\t c:$c\t d:$d"
test $b -gt $a
if [ $? -eq 0 ]
then
echo "b>a"
else
echo "ba"
fi
test $d -ge $c
if [ $? -eq 0 ]
then
echo "d>=c"
else
echo "dc"
fi
test $a -ne $d
if [ $? -eq 0 ]
then
echo "a!=d"
else
echo "a=d"
fi
运行脚本:
[root@node673 test]# ./test_int.sh
a:1 b:2 c:2 d:4
b>a
c>a
d>=c
b<=c
a!=d
test字符串比较的方法:
测试字符串长度 | -z |
测试字符串的长度为非零 | -n |
等于某一个字符串 | = |
不等于某一个字符串 | != |
#!/bin/bash
str1="asd"
str2='asd'
str3="123"
str4=""
echo -e "str1:${str1}\t str2:${str2}\t str3:${str3}\t str4:${str4}"
test -n $str1
if [ $? -eq 0 ]
then
echo "str1 is not empty"
else
echo "str1 is empty"
fi
test -z $str4
if [ $? -eq 0 ]
then
echo "str4 is empty"
else
echo "str4 is not empty"
fi
test $str1=$str2
if [ $? -eq 0 ]
then
echo "str1 = str2"
else
echo "str1 != str2"
fi
test $str1!=$str4
if [ $? -eq 0 ]
then
echo "str1 != str4"
else
echo "str1 = str4"
fi
运行脚本:
str1:asd str2:asd str3:123 str4:
str1 is not empty
str4 is empty
str1 = str2
str1 != str4
test逻辑比较的方法:
逻辑与 | -a |
逻辑或 | -o |
逻辑非 | ! |
例:
#!/bin/bash
basepath=$(pwd)
filename=$0
# 判断位置参数个数等于1,且第一个位置参数等于100
test $# -eq 1 -a $1 -eq 100
if [ $? -eq 0 ]
then
echo "位置参数数量为1个且值为100"
else
echo "不满足与运算的输入要求..."
fi
# 判断位置参数个数等于2,或第2个位置参数等于200
test $# -eq 2 -o $2 -gt 100
if [ $? -eq 0 ]
then
echo "位置参数为2个或第二个位置参数大于100"
else
echo "不满足或运算的输入要求..."
fi
运行脚本:
[root@node673 test]# ./test_logic.sh 200 200
不满足与运算的输入要求...
位置参数为2个或第二个位置参数大于100
test文件比较的方法:
文件存在且是一个常规文件 | -f |
文件不为空 | -s |
文件可读 | -w |
文件可写 | -r |
文件可执行 | -x |
文件是一个目录名 | -d |
文件是一个符号链接 | -h |
文件名引用一个字符设备 | -c |
文件名引用一个快文件 | -b |
例:
#!/bin/bash
base_path=$(pwd)
filename=$0
filename2="./nonexists.txt"
dir_name="./20190507"
test -f $filename
if [ $? -eq 0 ]
then
echo "$filename is a regular file"
else
echo "$filename is not exists or not a regular file"
fi
test -s $filename
if [ $? -eq 0 ]
then
echo "$filename is not empty..."
else
echo "$filename is empty..."
fi
test -r $filename
if [ $? -eq 0 ]
then
echo "$filename is readable"
else
echo "$filename is not readable"
fi
test -w $filename
if [ $? -eq 0 ]
then
echo "$filename is writeable"
else
echo "$filename is not writeable"
fi
test -x $filename
if [ $? -eq 0 ]
then
echo "$filename can be excute"
else
echo "$filename can not be excute"
fi
test -d $dir_name
if [ $? -eq 0 ]
then
echo "$dir_name is a directory..."
else
echo "$dir_name is not a directory"
fi
运行脚本:
[root@node673 test]# ./test_file.sh
./test_file.sh is a regular file
./test_file.sh is not empty...
./test_file.sh is readable
./test_file.sh is writeable
./test_file.sh can be excute
./20190507 is a directory...
# 查看./test_file.sh文件的信息
[root@node673 test]# ll ./test_file.sh
-rwxr-xr-x 1 root root 1217 5月 7 06:16 ./test_file.sh
“<<”可以被认为是一种重定向符,被放在输入重定向的命令之后,紧跟在<<的各行作为命令的输入,输入的结尾通过文件结束符表示,也可以自己定义定界符,定界符后的单词作为输入各行结束的定界符。结束的定界符要定格写。
#!/bin/bash
# 使用"<<"操作数据库,连接数据库后,先查看状态,再查询库test下user表的信息。以感叹号"!"作为定界符
/usr/local/mysql5.6/bin/mysql <
选择结构是程序中带有判断的一种逻辑结构,只有符合一定的条件,程序体才会被执行
单分支if结构,当条件满足时,执行then后面的语句,不满足条件直接退出判断语句
if [条件]
then
语句
if
双分支结构,当条件满足时,执行then后面的语句,不满足条件执行else后面的语句
if [条件]
then
语句
else
语句
if
case语句适用于多重分支的应用情况,当条件满足任一一个分支条件时,执行该分支后面的语句
case 变量名 in
模式1)
命令序列1
;;
模式2)
命令序列2
;;
*)
默认执行的命令序列
;;
esac
例:
#!/bin/bash
read -p "请输入一个字符,按回车确定: " key
case $key in
[0-9])
echo "你输入的是数字: $key"
;;
[a-z]|[A-Z])
echo "你输入的是字符: $key"
;;
*)
echo "你输入的是特殊字符: $key"
;;
esac
运行脚本:
[root@node673 test]# ./practice_case.sh
请输入一个字符,按回车确定: a
你输入的是字符: a
遍历/列表时循环结构
# 语法如下
for variable in list
do
statement
done
用seq命令可以生成一个一个数到另一个数之间的所有整数,经常配合for循环一起使用
#!/bin/bash
for i in $(seq 5)
do
echo "$i"
done
运行脚本:
[root@node673 test]# sh practice_for.sh
1
2
3
4
5
C语言风格的循环结构
# 语法如下:
for((expr1; expr2; expr3)) # 注意:是双括号
do
statement
done
当while条件为真时,执行循环体中的语句
# 语法如下:
while expression
do
statement
done
while循环结构分两种:
#!/bin/bash
i=1
while [ $i -le 5 ]
do
echo "$i"
let i++
done
运行脚本:
[root@node673 test]# sh practice_while.sh
1
2
3
4
5
break退出当前循环,continue退出本次循环
break:
#!/bin/bash
# 当输入字符为x或X时,循环终止。
while [ 1 ]
do
read -p "请输入一个字符,按回车确定:" key
test $key = x -o $key = X
if [ $? -eq 0 ]
then
echo "你输入的是$key,终止循环。"
break
else
echo “$key”
fi
done
运行脚本:
[root@node673 test]# sh practice_break.sh
请输入一个字符,按回车确定:a
“a”
请输入一个字符,按回车确定:1
“1”
请输入一个字符,按回车确定:x
你输入的是x,终止循环。
[root@node673 test]#
continue:
#!/bin/bash
# 当输入的字符为x或X时,只跳过本次循环
while [ 1 ]
do
read -p "请输入一个字符,按回车确认:" key
test $key = x -o $key = X
if [ $? -eq 0 ]
then
echo "你输入的是x或X,跳过本次循环。"
continue
else
echo "$key"
fi
done
运行脚本:
[root@node673 test]# sh practice_continue.sh
请输入一个字符,按回车确认:a
a
请输入一个字符,按回车确认:x
你输入的是x或X,跳过本次循环。
请输入一个字符,按回车确认:X
你输入的是x或X,跳过本次循环。
请输入一个字符,按回车确认:1
1
可以按行读入,一直到所有行都读完才退出循环。实际工作中经常采用这个结构进行数据的处理。
# 语法格式:
cat file.txt | while read line # 此处的cat也可以是产生若干行的命令,如find
do
statement
done
例:循环读入一个文件的所有行,每行按照格式输出第一个字段和第二个字段
#!/bin/bash
num=0
cat ./test.txt | while read line
do
let num++
echo -n "第$num行..."
one=`echo ${line} |awk '{print$1}'`
two=`echo ${line} |awk '{print$2}'`
echo "第一个字段为:$one-----第二个字段为:$two"
done
运行脚本:
[root@node673 test]# sh practice_while_read_line.sh
第1行...第一个字段为:北京市-----第二个字段为:11
第2行...第一个字段为:天津市-----第二个字段为:12
第3行...第一个字段为:上海市-----第二个字段为:31
第4行...第一个字段为:重庆市-----第二个字段为:50
第5行...第一个字段为:河北省-----第二个字段为:13
1、linux shell函数 将一组命令集或语句形成一个可用的块,这些块语句成为函数。
2、函数的组成:
3、函数定义的格式:
function 函数名() #function 可以省略 注意()内部不能带任何参数
{
命令1
命令2
...
}
例一:函数的定义和引用
#!/bin/bash
# 函数的定义及引用
function now_date()
{
echo "now date is `date`"
}
now_date
运行脚本:
[root@node673 test]# sh practice_function.sh
now date is 2019年 05月 09日 星期四 07:25:13 CST
例二:向函数传递参数
#!/bin/bash
function func_sum()
{
if [ $# -eq 2 ]
then
a1=$1
a2=$2
let sum=$a1+$a2
echo "$a1+$a2=$sum"
else
echo "输入的参数数量不正确..."
fi
}
# 在脚本中调用定义好的函数,可以传入多个位置参数
func_sum 10 20
运行脚本:
[root@node673 test]# sh practice_func.sh
10+20=30
例三:调用其他脚本文件中的函数,函数导入的方法:. 空格 文件名
#!/bin/bash
# 调用函数的文件位置和文件名称
. ./practice_func.sh
while [ 1 ]
do
read -p "please enter a file: " file
func_md5 $file
done
4、数组的定义:在程序设计中,为了处理方便,把具有相同类型的若干变量按有序的形式组织起来,这些按序排列的同类数据元素的集合称为数组。
# 定义一个数组:
数组名=(元素1 元素2 元素3) # 一对括号表示一个数组,数组间元素用空格符合隔开
#如:
myarray=(1 2 3 4 5)
5、数组的常用操作
#!/bin/bash
array=(0 1 2 3 4 5 6)
echo "数组: ${array[*]}"
echo "数组长度为: ${#array[*]}"
# 数组新增值,数组下标从0开始
array[7]=7
echo "数组新增后所有元素为: ${array[*]}"
# 数组删除值
unset array[0]
echo "数组删除数组第一个值后剩余元素: ${array[*]}"
# 数组修改值
array[0]=999
echo "修改后数组第一个值是: ${array[0]}"
# 数组查询值
echo "数组第一个值: ${array[0]}"
运行脚本:
[root@node673 test]# sh test_array1.sh
数组: 0 1 2 3 4 5 6
数组长度为: 7
数组新增后所有元素为: 0 1 2 3 4 5 6 7
数组删除数组第一个值后剩余元素: 1 2 3 4 5 6 7
修改后数组第一个值是: 999
数组第一个值: 999
1、向mysql数据库中批量执行批量插入
#!/bin/bash
# 定义数据库名
db_name="test"
# 定义表名
table_name="user"
# 定义导入数据的文件
import_file=./data.txt
cat $import_file | while read line
do
u=$`echo $line |awk '{print $1}'` # 获取每一行的第一个字段
p=$`echo $line |awk '{print $2}'` # 获取每一行的第二个字段
echo "$u $p"
/usr/local/mysql5.6/bin/mysql -uroot -proot -e "insert into $db_name.$table_name(username,password) values ('$u','$p')";
done
首先检查有无语法错误:
[root@node673 test]# sh -n test.sh
没有输出,说明没有错误,开始实际调试:
[root@node673 test]# sh -x test.sh
调试结果如下:
+ [ 1 -eq 2 ]
+ echo 1
1
+ [ 2 -eq 2 ]
+ continue
+ [ 3 -eq 2 ]
+ echo 3
3