为什么要学习shell script
脚本分多种类别,如shell、python、bat等,不同的场合下使用不同的脚本,python应用的范围最广,日常办公、大数据搜集、网络爬虫等都可以使用,bat是windows下的脚本文件。在本文中,只总结一些关于shell的语法,对于Linux工程师,我们都很熟悉shell,与Linux内核打交道需要shell,还有Android系统、Linux系统的编译都有shell的参与,因为shell脚本的存在,我们执行编译命令时不用手动敲击一堆命令,它可以解放我们的双手,自动化地帮助我们完成一些工作。
shell script规则
shell script其实是一个纯文本文件,只是我们给予了它一些规则后变成了不需要编译就可以直接运行的程序,如下:
- 命令的执行顺序:从上而下,自左向右。
- 命令、参数间的多个空白都会被忽略掉。
- 空白行也将被忽略掉,即使是[tab]按键所得的空白行也会被忽略掉。
- 如果读取到一个Enter符号,就尝试开始执行该行命令。
- 如果一行的内容太多,可以使用“[Enter]”来扩展到下一行。
- "#"作为批注,后面的字符将被忽略,不会被执行。
- shell script文件以 *.sh 为扩展名,并且必须赋予可执行权限。
- 执行 test.sh 文件(以test.sh文件为例)最常用的方法是进入test.sh文件所在的目录下,敲击 ./test.sh 。
- 有时也将test.sh文件放在PATH路径下,这样也可以通过 sh test.sh 来执行shell script。
hello world
很自然,编写hello world是学习一种语言的第一步,对于shell script亦是如此,通过一个简单的 hello world 程序来学习编写shell script的基本规则。
#!/bin/bash
# Program:
# This program shows "Hello world" in your screen.
# History:
# 2021/08/3 Zhengqing.Yang First release
echo "Hello World!"
exit 0
对以上shell script做一些解释:
-
第一行
#!/bin/bash
声明这个script使用的shell名称
当程序被执行时,它就能够加载bash的相关环境配置文件,一般是~/.bashrc
,并且调用bash执行下面的命令。如果没有声明这一行,系统无法识别该文件,从而无法成功执行。 -
程序内容说明
除了 “#!” 外,其余所有 “#” 后面的内容都是注释,在shell script中只有 “#” 能起到注释的作用,"//" 和 "/**/"都不行。
每一条语句后面没有 “;” 分号结尾,在shell script中分号的作用是执行连续的命令。
一些必要的程序声明,比如功能、版本号、作者等,这种好习惯对于以后程序的维护有很大的帮助。 -
echo 命令是用于字符串的输出,exit 0表示脚本执行完成后回传一个0给系统,用户可以在命令行模式下敲击
echo $?
获取其返回值。其实, Linux下的命令执行结束后,也会返回一个值,一般情况下,命令执行成功返回0,失败返回非0 值,所以在写shell脚本时,我们也可以学它返回一个值。
循序渐进
交互式脚本
我们也许会有这样的经历,在我们安装程序的时候,有时候系统会反问我们要安装到哪个目录去,是否确定安装之类的,这就是人机交互,在这种现像的背后,其实是脚本默默地在运行,它指挥着系统做一些我们希望完成的事情。那么在Linux下如何实现人机交互呢?交互,说的是输入和输出,站在脚本的角度来说,将数据从命令行读到变量中就叫输入,将变量的值输出到命令行叫输出,在shell脚本语法中仅仅通过两个命令就可以实现输入输出。
#!/bin/bash
# Program:
# This program shows "Hello world" in your screen.
# History:
# 2021/08/3 Zhengqing.Yang First release
read -p "Please input your first name: " firstname
read -p "Please input your last name: " lastname
echo "Your full name is:$firstname $lastname"
exit 0
read
是从命令行读取内容,将内容保存在变量firstname和lastname中,-p表示在执行读操作前打印提示信息。- $firstname,$lastname表示获取这两个变量的值,
echo
命令将其打印到屏幕上,如图1所示。
![](https://img-blog.csdnimg.cn/8076c00036364b4095ed267a7c9c1c8b.png)
利用日期命名文件
在数据库的维护中,或者在debug程序的时候,可能需要我们创建很多的log文件,创建文件对于我们来说不是难事,记住一两个文件也是小case,但是对于文件数目很多,时间有长久的情况下呢,这就难度大了,可能记不清各个文件是干什么用的,什么时候创建的,有时候真的会苦恼于这些文件的命名方式。对于在需要创建多个文件的情况下,我们可以使用“功能+日期”这种命名方式。
1
2 #!/bin/bash
3
4 # Program:
5 # Program creates three files,which named by user's input
6 # and date command.
7 # History:
8 # 2021/08/3 Zhengqing.Yang First release
9
10
11 #打印提示信息
12 echo "I will use 'touch' command to create 3 files."
13
14 #从标准输入读取文件名
15 read -p "Please input your filename: " fileuser
16
17 #判断是否输入了文件名
18 filename=${fileuser:-"filename"}
19
20 #利用date命令获取时间
21 date1=$(date --date='2 days ago' +%Y%m%d) #前两天的日期
22 date2=$(date --date='1 days ago' +%Y%m%d) #前一天的日期
23 date3=$(date +%Y%m%d) #今天的日期
24
25 #整合文件名
26 file1=${filename}${date1}
27 file2=${filename}${date2}
28 file3=${filename}${date3}
29
30 #创建文件
31 touch "$file1"
32 touch "$file2"
33 touch "$file3"
34
35 exit 0
s h e l l 语 法 分 析 : \color{Crimson}{shell语法分析:} shell语法分析:
- file1=${filename}${date1}
这条语句的模型是${变量},意思是分别获取变量filename和date1的值,并组合在一起赋值给变量file1。 - date3=$(date +%Y%m%d)
$()里面装的是命令,模型是$(变量),这条语句的意思首先执行date命令,然后通过$获取date命令的结果,最后赋值给变量date3。 - filename=${fileuser:-“filename”}
若变量fileuser为空时,取string filename为值,若不为空,则取变量fileuser为值。其变种还有三种,分别为:
(1)filename=${fileuser:=“filename”}:规则和上面第一个一样。
(2)filename=${fileuser:+“filename”}:规则跟上面的相反,当fileuser不为空时取string filename,fileuser为空时,取空值。
(3)filename=${fileuser:?“filename”}:当fileuser不为空时,取fileuser的值,当fileuser为空时,string filename输出到标准错误中,并退出程序。 - “string”
双眼号里面的是字符串。 - $((运算内容))
美元符+双括号的功能是算数运算,比如+、-、*、/、%,shell支持整数计算。
判断文件是否存在
判断文件存在与否,在Linux 命令行模式下可以使用find
命令,也可以使用test
命名,一般情况下,find
命令会用的多一些,shell脚本中通常使用test
,test
命令的功能强大,不仅仅只用于文件,它还可以用于判断字符串是否为空,是否相等 ,以及变量的大小等,在这里我们学习shell脚本下test的使用方法,程序的逻辑如下:
- 让用户输入一个文件名,然后判断该文件是否存在,若不存在,则打印“File is not exit”,并中断程序;
- 若这个文件存在,则判断是文件还是目录,结果输出“File is regular file”或“File is directory”;
- 若该文件存在,输出程序执行者对该文件或目录的权限数据。
2 #!/bin/bash
3
4 # Program:
5 # User input a filename,Program will check the flowing:
6 # 1.)exit? 2.file/directory 3.)file permission
7 # History:
8 # 2021/08/05 Zhengqing.Yang First release
9
10 #打印提示信息
11 echo "Please input a filename,I will check the filename's type and permission"
12
13 #用户输入文件名
14 read -p "Input a filename: " filename
15
16 #判断文件名是否为空
17 test -z $filename && echo "You must input a filname." && exit 0
18
19 #判断文件是否存在,若不存在则显示信息并退出程序
20 test ! -e $filename && echo "The file '$filename' is not exit." && exit 0
21
22 #判断文件类型与属性
23 test -f $filename && filetype="regular file"
24 test -d $filename && filetype="directory"
25 test -r $filename && perm="readable"
26 test -w $filename && perm="$perm writable"
27 test -x $filename && perm="$perm executable"
28
29 #输出最终结果信息
30 echo "The file: $filename is a $filetype"
31 echo "And the permission are: $perm"
32
33 exit 0
s
h
e
l
l
语
法
分
析
:
\color{Crimson}{shell语法分析:}
shell语法分析:
在上面的程序中,主要语法是test命令,其他一些基本语法在前面已经了解过,关于test命令一些常用的选项在下表列出:
选项 | 代表意义 |
---|---|
test -z string | 判断字符串是否为空,若string位空,则为true |
! | 反向状态,如test ! -x file,当file 不具有-x时,回传true |
-e | 该文件是否存在 |
-f | 该文件是否存在且为文件 |
-d | 该目录是否存在且为目录 |
-r | 检测该文件是否存在且具有可读权限 |
-w | 检测该文件是否存在且具有可写权限 |
-x | 检测该文件是否存在且具有可执行权限 |
-o | 任何一个条件成立!类似 ||(或) |
-a | 两个条件同时成立!类似&&(与) |
-lt | test n1 -lt n2,n1 小于等于 n2 |
中括号[]的用法
在shell script中,具有判断功能的语法不仅仅只有test命令,还有中括号[],用法与test一模一样,只是需要注意以下几点:
- 在中括号[]内的每个组件都需要有空格键来分隔。
- 在中括号[]内的变量,最好都以双引号括号起来。
- 在中括号[]内的常量,最好都以单或双引号括号起来,否则会出现以下这样的错误。原因是翻译过来就是这样的,[ hello world == “hello” ],中括号[]判定式只能有两个参数,所以发生错误了。
![](https://img-blog.csdnimg.cn/d833e3ae4c064447b37498e1fed2f040.png)
正确的写法应该是:[ “$name” == “hello” ]
4. test 和 [] 中,==和!=只能用于比较字符串,而且结果为真时,返回1,结果为假时,返回0。
简单写个小程序:
1
2 #!/bin/bash
3
4 # Program:
5 # This program shows the user's choice.
6 # History:
7 # 2021/08/05 Zhengqing.Yang First release
8
9 #从标准输入读取字符串
10 read -p "Please input (Y/N): " yn
11
12 #判断是否输入 y或Y
13 [ "$yn" == "Y" -o "$yn" == "y" ] && echo "OK,continue" && exit 0
14
15 #判断是否输入 n或N
16 [ "$yn" == "N" -o "$yn" == "n" ] && echo "OK,interrupt" && exit 0
17
18 #打印提示信息
19 echo "I don't known what you choice is" && exit 0
20
21 exit 0
s
h
e
l
l
语
法
分
析
:
\color{Crimson}{shell语法分析:}
shell语法分析:
用户输入y或n,忽略大小写,程序判断是否输入了y或n,若是,则返回1,继续执行&&后面的语句。在中括号[]中,-o是test命令的选项,表示任何一个条件成立都返回1。
![](https://img-blog.csdnimg.cn/f5cf6f2eae3f4b4e8e85886079a4fdd0.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjQxOTk1Mg==,size_16,color_FFFFFF,t_70)
2 #!/bin/bash
3
4 # Program:
5 # This program shows script name,parameters.
6 # History:
7 # 2021/08/07 Zhengqing.Yang First release
8
9 #输出脚本的文件名
10 echo "The script name is ==> $0"
11 #输出参数的个数
12 echo "Total parameter number is ==> $#"
13 #判断参数的个数是否小于2个,若是则打印提示信息并退出程序
14 [ $# -lt 2 ] && echo "The number of parameter is less than 2. Stop here." && exit 0
15 #打印全部参数
16 echo "Your whole parameter is ==> $@"
17 #打印第一个参数
18 echo "The 1st parameter ==> $1"
19 #打印第二个参数
20 echo "The 2nd parameter ==> $2"
21
22 exit 0
除此之外,还有一个偏移变量的命令shift,可以做偏移变量的操作,从右往左偏移,最左边的变量将会被移除。将上面的程序稍加修改一下:
2 #!/bin/bash
3
4 # Program:
5 # This program shows script name,parameters.
6 # History:
7 # 2021/08/07 Zhengqing.Yang First release
8
9 #输出脚本的文件名
10 echo "The script name is ==> $0"
11
12 #判断参数的个数是否小于2个,若是则打印提示信息并退出程序
13 [ $# -lt 2 ] && echo "The number of parameter is less than 2. Stop here." && exit 0
14
15 #打印第一次偏移之前的参数个数和全部参数
16 echo "Total parameter number is ==> $#"
17 echo "Your whole parameter is ==> $@"
18
19 shift #第一偏移,默认移除第一个参数
20
21 #打印第一次偏移之后的参数个数和全部参数
22 echo "第一次偏移之后:"
23 echo "Total parameter number is ==> $#"
24 echo "Your whole parameter is ==> $@"
25
26 shift 3 #第二次变量偏移,表示移除前面三个参数
27
28 #打印第二次偏移之后的参数个数和全部参数
29 echo "第二次偏移之后:"
30 echo "Total parameter number is ==> $#"
31 echo "Your whole parameter is ==> $@"
32
33 exit 0
条件判断式
if…then
类似c、c++、java语言,shell script也有if语句,只不过它们在形式上有所区别,在功能上完全一样。在shell script中,if判断式如下:
if [ 条件判断式一 ]; then
当条件判断式一成立时,可以进行命令的工作内容;
elif [ 条件判断式二 ]; then
当条件判断式二成立时,可以进行命令的工作内容;
else
当条件判断式一和二都不成立时,可以进行命令的工作内容;
fi
将前面判断yn的程序使用if then改写一下会不会变得简单易读一些呢?
1
2 #!/bin/bash
3
4 # Program:
5 # This program shows the user's choice.
6 # History:
7 # 2021/08/05 Zhengqing.Yang First release
8
9 #从标准输入读取字符串
10 read -p "Please input (Y/N): " yn
11
12 #判断是否输入 y或Y/n或N
13 if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
14 echo "OK, continue"
15 exit 0
16
17 elif [ "$yn" == "N" ] || [ "$yn" == "n" ]; then
18 echo "Oh, interrupt"
19 exit 0
20 else
21 echo "I don't known what you choice is"
22 exit 0
23 fi
显然,这种格式接近于c语言以及其他高级语言的if判断式,对于我们来说很熟悉,程序简单易读,易懂,易理解。
看书总结的过程中,看到一个例子觉得不错,它主要功能是计算士兵还有多久可以退伍的天数。正好我也有几个参军入伍的朋友,我们时常还存在着联系,正好借着学习一下这个程序的机会,算算还有多久能和这几个朋友一起喝酒。
其实程序逻辑比较简单,首先让朋友输入一个退伍的日期,然后与现在的日期做减法运算。日期怎么做减法呢?将日期转换成秒数再相减,最后再把结果转换成天数就可以了。
2 #!/bin/bash
3
4 # Program:
5 # You input your demobilization date.I calculate how many days
6 # before you demobilize.
7 # History:
8 # 2021/08/07 Zhengqing.Yang First release
9
10 #打印提示信息,告知用户应该输入的日期格式
11 read -p "Please input your demobilization date (format: 20090401):" date2
12
13 #判断一下输入内容是否正确
14 date_d=$(echo $date2 | grep '[0-9]\{8\}') #判断是否有连续的八个数字
15 if [ "$date_d" == "" ]; then
16 echo "You input the wrong date format"
17 exit 1
18 fi
19 #开始计算日期
20
21 #声明整型变量
22 declare -i date_dem
23 declare -i date_now
24 declare -i date_total_s
25 declare -i date_d
26 declare -i date_h
27
28 #计算
29 date_dem=`date --date="$date2" +%s`#退伍日期秒数
30 date_now=`date +%s`#当前日期的秒数
31 date_total_s=$(($date_dem-$date_now))#日期之差
32 date_d=$(($date_total_s/60/60/24))#转为天数
34 #判断是否已经退伍
35 if [ "$date_total_s" -lt "0" ]; then
36 echo "You had been demobilization before: "$((-1*date_d))" ago"
37 else
38 date_h=$(($(($date_total_s-$date_d*60*60*24))/60/60))
39 echo "You will demobilize after $date_d days and $date_h hours"
40 fi
41 exit 0
42
s h e l l 语 法 分 析 : \color{Crimson}{shell语法分析:} shell语法分析:
- `命令`
这个语法与$(命令)的作用是一样,都是命令替换的,里面包含的命令可以在shell下单独执行。 - [0-9]{8}
判断一串字符串中是否包含连续8个数字。 - declare -i
在shell script中声明一个整型变量。
case…esac
同样shell script中也有类似于c语言中的switch..case
功能的语句,一般称它为开关语句,它在格式上跟switch..case
大不一样,语法奇奇怪怪的。
case $变量的名称 in
"第一个变量内容")
程序段
;;
"第二个变量内容"
程序段
;;
*)
exit 1;
;;
esac
从上面的语法来看,case程序段是以case开头,esac结尾的。除此之外,每一个变量内容之后有一个右括号)
,并且程序段后面另起一行用双分号;
来代表这个程序段的结束。
*)
这个符号类似于switch...case
里面的default
,当输入的变量内容不符合第一个和第二个时,执行这一语句,我们通常可以用来告知用户一些提示信息。
不妨用一个简单的程序来具体感受一下这个case程序段的用法。例如,从标准输入获取one/two/three,通过程序判断后输出。
1
2 #!/bin/bash
3
4 # Program:
5 # This script only accepts the flowing parameter:one,two or three.
6 # History:
7 # 2021/08/07 Zhengqing.Yang First release
8
9 echo "This program will print your selection !"
10
11 #从标准输入获取字符串
12 read -p "Input your choice:" choice
13
14 #开始判断
15 case $choice in
16 "one")
17 echo "Your choice is ONE"
18 ;;
19 "two")
20 echo "Your choice is TWO"
21 ;;
22 "three")
23 echo "Your choice is THREE"
24 ;;
25 *)
26 echo "Input error !"
27 ;;
28 esac
29
30 exit 0
function 功能
function功能其实就是函数功能,将一连串命令打包起来,类似自定义一个执行命令的东西,好处在于简化程序,增加shell脚本的可移植性,以于维护脚本,还可以用function功能自定义一些命令行模式下使用的命令。function的语法如下:
function fname()
{
}
和C语言中的函数定义很像,只不过在这里没有返回值和参数列表而已,虽然没有参数列表,但是可以传参。如何定义function和传参呢?
1
2 #!/bin/bash
3 # Program:
4 # Use function to repeat information.
5 # History:
6 # 2021/08/07 Zhengqing.Yang First release
7
8 function printit()
9 {
10 echo "Your choice is $1"
11 }
12
13 echo "This program will print your selection !"
14
15 read -p "Input your choice (one ,two or three): " choice
16
17 case $choice in
18 "one")
19 printit "ONE"
20 ;;
21 "two")
22 printit "TWO"
23 ;;
24 "three")
25 printit "THREE"
26 ;;
27 *)
28 echo "Input error !"
29 ;;
30 esac
31
32
33 exit 0
function也有内置的变量,它与shell script很类似,$0
代表函数名,$1
、$2
、$3
…代表后面接的参数,这里特别要注意与shell script区分,它们的作用域不同。在上面的程序中,printit是函数名,“ONE”,"TWO"和"THREE"是传进去的参数,在printit函数体中,$1
是接收参数的变量。
在shell function中,也有关键字return
,当函数调用结束时,可以返回一个值,若不显示return
,则默认返回上一次命令的状态值。在function里,返回0代表执行成功,返回非0代表执行失败。
在这里还想谈谈shell中变量的定义,在shell中,也有全局变量和局部变量之分:
全局变量:在shell中定义的变量都是全局变量,其作用域从变量定义的地方开始,直到shell结束或者变量删除的地方。删除变量的语法是unset 变量
。
局部变量:其实不管是在function之内还是之外定义的变量都属于全局变量,当在function内定义变量用local
关键字声明时才是局部变量,其作用域仅限函数体内。如果在一个function中,局部变量和全局变量的名字相同,则只有局部变量生效。
循环
常见的循环结构有三种,分别是while do done
、until do done
、for do done
。
- while do done结构
while [ 条件 ]
do
程序段
done
举个例子:计算1+2+3+…+100的值
#!/bin/bash
# Program:
# Use loop calculate "1+2+3+...+100" result.
# History:
# 2021/08/07 Zhengqing.Yang First release
declare -i result=0 #存放结果
declare -i i=0 #循环因子
while [ "$i" != "100" ]
do
i=$(($i+1))
result=$(($result+$i))
done
echo "The result of 1+2+3+...+100 is ==> $result"
exit 0
s h e l l 语 法 分 析 : \color{Crimson}{shell语法分析:} shell语法分析:变量声明declare可以用也可以不用,declare主要用于声明变量并设置变量的属性和显示函数。当设置了属性之后,这个变量只能存储该类型的数据了,若不设置的话,这个变量可以存储任何类型的数值。显示函数是什么意思呢?就是在运行shell脚本的时候,将前面定义的function函数打印在屏幕上。
- until do done
until [ 条件 ]
do
程序段
done
until与while的区别:其实从中文意思上就可以理解,until中文译为直到...时候
,在程序里边意思就是直到条件成立时才跳出循环,while中文译为当...的时候
,意思是当条件成立时,执行循环,条件不成时,跳出循环。
举个例子:输入一个值,计算从1累加到该值的结果,例如我输入10,计算1+2+3+…+10 的值。
#!/bin/bash
# Program:
# Until do done ---demo.
# History:
# 2021/08/07 Zhengqing.Yang First release
result=0
i=0
read -p "Please input one digit: " d
until [ "$i" == "$d" ]
do
i=$(($i+1))
result=$(($result+$i))
done
echo "The result is ==> $result"
exit 0
- for do done
for循环有两种语法,第一种主要用于非数值处理,第二种主要用于数值处理,第二种类似于c语言里边的for循环。
第一种语法如下:
for var in con1 con2 con3 ...
do
程序段
done
var变量的内容在循环工作时,依次为con1 con2 con3…,在实际应用中我们一般不会这样写,因为灵活性不高,而且费体力。在一些需要循环100次的程序中,不会有人在后面写100个循环因子吧。那应该如何巧妙的使用这个语法呢,用两个例子进行说明吧。
例子1:列出系统中所有账号的名称、标识符和特殊参数。
#!/bin/bash
# Program:
# for do done --demo 1.
# History:
# 2021/08/7 Zhengqing.Yang First release
users=$(cut -d ':' -f1 /etc/passwd) #获取所有的账户名称
for username in $users
do
id $username
finger $username
done
exit 0
s h e l l 语 法 分 析 : \color{Crimson}{shell语法分析:} shell语法分析:
- cut命令
从文件的每一行剪切字符、字段、字节。cut -d ':' -f1 /etc/passwd
,-d 指定分隔符,这里以:
作为分隔符,-f1指剪切第一个域,最后的是文件名。 - id命令
用于显示用户ID,群组ID。 - finger命令
用户显示用户信息。
例子2:ping测试局域网内的100台主机。
#!/bin/bash
# Program:
# This program shows "Hello world" in your screen.
# History:
# 2021/08/3 Zhengqing.Yang First release
network="192.168.172"
for sitenu in $(seq 1 100)
do
#取得ping命令的回传值
ping -c 1 -w 1 $network.$sitenu &> /dev/null && result=0 || result=1
#判断各个主机是否连通
if [ "$result" == 0 ]; then
echo "Server $network.$sitenu is up"
else
echo "Server $network.$sitenu is down"
fi
done
exit 0
s h e l l 语 法 分 析 : \color{Crimson}{shell语法分析:} shell语法分析:
- ping命令
-c 1 发送一个数据包,-w 1 等待响应时间为1秒。 - &> file
将标准输出和标准错误重定向到file文件 - && 和 || 一起连用
命令 | 含义 |
---|---|
[ -z “string” ] && echo 0 || echo 1 | 若string位空,则执行echo 0,否则执行echo 1 |
[ -z “string” ] || echo 0 && echo 1 | 若string位空,则执行echo 1,否则执行echo 0 |
第二种语法如下:
for (( 初始值; 限制值; 执行步长 ))
do
程序段
done
shell script中的for循环在格式上比c语言的for循环多了一个括号而已,其功能以及括号中所表达的意思是一样的。这种语法适合用于数值方式的运算,可以简单改写一个程序感受一下。
#!/bin/bash
# Program:
# for do done --demo 2.
# History:
# 2021/08/08 Zhengqing.Yang First release
read -p "Please input a number,I will count for 1+2+3+...+your_input: " nu
result=0
for(( i=0; i<=$nu; i=i+1 ))
do
result=$(($result+$i))
done
echo "The result of 1+2+3+...+$nu ==> $result"
exit 0
程序实现的功能是累加计算,例如用户输入10,程序计算出1+2+3+…+10的结果。可以看到两种for循环的语法不同,应用场景也不同,在不同的场景下使用不同的语法会使程序更加简单易读。
文本处理
sed命令
sed命令主要用于自动编辑一个或多个文件,每次处理一行内容,可以对文件进行替换、行新增、行删除、行选取等操作,简化对文件的反复操作。对文件处理的原理是将当前要处理的行保存在临时缓冲区,接着sed命令去处理缓冲区的内容,处理完后,将缓冲区的内容送往屏幕,接着再处理下一行,反反复复,直到文件结尾。关于sed的用法网上有很多介绍,这里不做总结。
sed命令有两种语法,分别是:
sed [optiions] 'command' file
sed [options] -f scriptfile file
:-f 添加脚本文件到运行列表
关于详细的sed使用方法可以参考此贴:Linux sed命令示例解析
awk命令
awk命令也是用于文本分析的工具,逐行读入,默认以空格、制表符为分隔符将每行切片,切开的部分再进行各种分析。但是它是一种编程语言,而sed是一种流编辑器。
Linux下对文本的处理的工具还有grep
,这三者搭配着正则表达式
一起使用可以发挥出强大的作用。针对这三个工具更加详细的信息可以参考链接:Linux文本三剑客
shell script的追踪和调试
sh
命令可以用来debug shell脚本,根据sh命令的选项可以追踪和调试程序,常用到几个sh命令选项如下:
- -n :不要执行脚本,仅查询语法的问题
- -v:在执行脚本前,先将脚本的内容打印到屏幕上
- -x:将使用到脚本打印到屏幕上。
使用sh -n sh15.sh
命令就可以检查脚本语法了,这里第13行有语法错误,意思是错误的循环变量。查看程序,果然如此,变量之前没带$。还有一个原因,ubuntu将默认的bash shell更换成了dash shell,dash shell 不支持这种语法的for循环。将它更换为bash shell就可以了,具体做法参考以下链接:
https://blog.csdn.net/liuqinglong_along/article/details/52191382