linux shell 编程与实践

目录

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调试


shell编程

1、创建方法:用vi编辑器创建 如:vi hello.sh

2、编辑脚本文件需要注意的内容:第一行以“#!”开头,声明所使用的shell的全路径,如:#!/bin/bash

3、赋予可执行权限:chmod +x hello.sh  执行:./hello.sh

shell 关键字

常用的关键字如下:

1. echo

输出打印文字到屏幕

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]# 

2. exec

执行另一个 shell脚本

#!/bin/bash

exec ./hello.sh

3. read

读取标准输入

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

4. expr

对整数型变量进行算术运算,也可以进行字符串的相关运算

①. 对整数型变量进行算术运算:

使用方法: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

5. let

只执行整数的相关运算,运算结果也只能保存整数

使用方法: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

6. test

对两个值进行比较,比较成功返回0,否则返回非0

常用的比较方法:

  1. 整数比较
  2. 字符串比较
  3. 逻辑比较(与、或、非)
  4. 文件比较

使用方法: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

 7. “<<”

“<<”可以被认为是一种重定向符,被放在输入重定向的命令之后,紧跟在<<的各行作为命令的输入,输入的结尾通过文件结束符表示,也可以自己定义定界符,定界符后的单词作为输入各行结束的定界符。结束的定界符要定格写。

#!/bin/bash

# 使用"<<"操作数据库,连接数据库后,先查看状态,再查询库test下user表的信息。以感叹号"!"作为定界符
/usr/local/mysql5.6/bin/mysql <

三 Shell程序中的选择结构

选择结构是程序中带有判断的一种逻辑结构,只有符合一定的条件,程序体才会被执行

1. if-then控制结构

单分支if结构,当条件满足时,执行then后面的语句,不满足条件直接退出判断语句

if [条件]
    then
        语句
if

 双分支结构,当条件满足时,执行then后面的语句,不满足条件执行else后面的语句

if [条件]
    then
        语句
    else
        语句
if

2. case-esac控制结构

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

 四 Shell程序中的循环结构

1. for

遍历/列表时循环结构

# 语法如下
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

 2. while

当while条件为真时,执行循环体中的语句

# 语法如下:
while expression
    do
        statement
    done

while循环结构分两种:

  1. while [] 结构,此时while后面要加空格,否则会报错,如: while [ $? -eq 0 ]
  2. while(()) 结构,while后面不用加空格,如:while((i<10))
#!/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

 3. break、continue

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

 4. while read line

可以按行读入,一直到所有行都读完才退出循环。实际工作中经常采用这个结构进行数据的处理。

# 语法格式:

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、数组的常用操作

  • 读取数组的某一个元素:echo ${myarray[下标值]}  数组名必须用{}括起来,下标值从0开始编号。
  • 数组元素的赋值:myarray[下标值]=具体的值 如 myarray[5]=6
  • 显示数组所有元素:echo ${myarray[*]}
  • 获取数组长度:echo ${#myarray[*]}
  • 删除数组中的元素:unset myarray[下标值]
#!/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

六 shell实现数据库的批量插入

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

七 shell调试

首先检查有无语法错误:

[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

 

你可能感兴趣的:(LinuxShell)