Linux命令行+SHELL编程学习(2)

上篇说到命令行的基本操作,这一篇就谈谈常用的命令吗?不是的,因为这是我的学习笔记。而我暑假的学习目的主要是shell脚本编程。基本的命令大家都懂一些,但是说到写脚本,许多同学根本就没碰过。这一篇就是讲基本的脚本编程知识,包括输入输出、变量、函数、控制流等基本的语言特性。

Shell脚本的基本知识

Shell脚本以#作为注释符号,通常在脚本的第一行是

#! /bin/bash

我一直以为这就是注释,毫无意义的。今天才知道,这的确是注释,但同时也非常重要,它说明了要使用什么程序来解释这个脚本,例如

#! /usr/bin/Python

就会让python来执行这个脚本,而

#! /bin/rm

会直接删掉这个脚本文件

鄙视

这还真是有够蛋疼的。

Linux shell可执行的命令有3种,内建命令,shell函数和外部命令。

内建命令就是shell自己包含的命令,在脚本文件里自动高亮的那些就是内建命令。比如cd,echo什么的。

shell函数就是一个函数。

外部命令就是我们常说的可执行文件,比如新手必写的helloworld程序,我们自己的脚本程序test.sh。此外许多命令如find,grep也是外部命令(可以理解为系统预装的程序比如计算器写字板画图之类的)

外部命令的最大特点就是执行它们会引入新的进程,就是shell先fork一个子进程,然后excv一把,于是子进程就变成了外部命令程序(这个感觉好像OS的内容啊)

shell是弱类型、动态类型的语言。变量不需要预先声明类型,而且因为它只有一种类型即字符串,自然也不存在什么类型转换的问题。但是一定条件下整数运算和比较操作也是可以执行的。变量名的规定和C一样。值的话都是字符串啊(反正你键盘输入的也就只有字符串了),如果中间有空格的话要加引号。说到引号要提一下三种引号:

“双引号”:就是。。双。。引号,表示弱引用,神马是弱引用以后再说。

'单引号':就是。。单。。引号,表示强引用。

`反引号`:就是。。数字1旁边的那个建,和~同一个键,这个要注意不要当成单引号哦。反引号用来表示执行命令什么的。

继续说变量的事,比如我现在有个变量表示文件名

file=hehe.txt

注意等号旁边不能有任何空格(写C和java习惯空格的人伤不起)

如果文件名有空格的话,要用单或双引号引起来

file="hehe woquxizaole youkongzailiao.txt"

在程序中需要用到变量的值的时候,不是直接写变量名,而是在前面加个$

echo $file

就会输出file的值。

其实$file是${file}的简写,有时候直接写$file会引起错误,就要加上{}了,就和latex里面的上标下标一个意思。

环境变量是常识,忽略。

shell里面变量什么都不写的话是全局变量,函数里面可以用local关键字来指明是局部变量。

输入输出

有人说过HelloWorld有害,因为它不能很好体现一门语言的特性,所以这里我们就不拿它做例子了,我们用A+B Problem来教学吧。

#! /bin/bash

let sum="$1+$2"

echo "$1 + $2 = $sum"

代码中的$1和$2分别表示第1个和第2个参数(感觉好像废话啊)。0~9的参数都可以这么表示,超过10的话,加{},如${12}。和C里面一样,脚本名自身是第0个参数。说到这里又想起操作系统如何给程序传递参数了,OS给我带来的阴影果然很深很深很深很深。不过我们这里只需要很嗨皮地知道有这些参数就好了。let语句是做一个运算,大家都能看到,sum并没有事先声明类型。echo语句是把后面的字符串输出,因为双引号是弱引用,所以里面的变量名会替换成值,如果使用单引号的话就会原样输出了。

C的main函数是void main(int argc, char** argv)。其实shell也差不多,特殊变量$#表示了参数个数(不包括参数0),而$@就是参数列表。

重定向和管道是很重要的内容。简单滴说,>重定向标准输出,<重定向标准输入,>>追加文件。

add.sh 1 2 > sum.txt即把结果写到sum.txt文件中,原来的内容被无情地抛弃。

add.sh < input.txt即从文件input.txt中得到输入参数

add.sh 1 2 >> sum.txt把结果写到文件的末尾。

管道的作用是将前面的输出作为后面的输入(突然想到了人体蜈蚣这种重口低俗的电影来了),比较文雅的比方是一条流水线,例如

ls | grep "hehe"

ls命令列出所有文件,然后grep从中找出带有"hehe"的文件。最终的输出就是文件名包含"hehe"的所有文件名。顺带提一下,grep支持正则表达式,后面会专门学习正则表达式。

函数

函数的格式如下

functionname()

{

爱写什么写什么

}

我看的资料上对函数的参数没有很详细的说明,我理解的就是所有函数都是不定参数的(那个括号到底有什么用啊)。反正调用函数的时候也是func arg1 arg2 arg3这样调用。函数里面可以写return语句返回一个0~255的状态码,一般0表示正常。如果在函数里面写exit,会退出整个脚本(突然又想到了exit()系统调用,OS严重阴魂不散)。

控制流

shell里面的控制流语句有if-else,while,for,until,case几种,支持break和continue,没有goto。

先说逻辑操作,支持&&,||,!与或非三种运算。一般条件表达式都用test来做

test "2>3"

也可以简写做

[ "2>3" ]

那个方括号就是test的意思。

其实shell中并没有布尔值这种说法,只有成功和失败,0=成功=真,这和C里面0表示假的设定正好相反。

然后给出各控制语句的格式

if condition

then

statement

elif

statement

else

statement

fi

注意最后的结尾是fi,就是if反过来。

case expr in

pattern1)

statement;;

pattern2 | pattern3)

statements;;

esac

木有default这个说法。多个选项可以写在一起表示或的关系,如

case $1 in

1)

echo "hehe";;

2 | 3)

echo "haha";;

esac

那么参数一为2或3时都将输出haha。另外,结束的标志也是case反过来,即esac。

for var [in list]

do

statement

done

就是将list中的各项依次代入var中执行循环。如果省略了list,就默认为$@。

while/until condition

do

statement

done

这个就不解释了,until和while的区别就是一个为真时退出一个为假时退出。

shell没有goto语句。老实说goto还是挺好用的,虽然滥用会导致程序非常非常难懂。一个函数里面用goto跳到统一的错误处理部分是一个很好的办法(尤其在网络编程那种动不动就要检查错误的地方)。但是shell提供了带标号的break和continue语句。

break x表示跳出几层循环,省略的话就默认一层。

最后加一个shift命令。它的作用是将整个参数列表前移,同时参数个数减一。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/e3469a5ce3af2836a46701aa80d77e31.html