一、shell基础
1、shell的基本概念
shell就是系统跟计算机硬件交互时使用的中间介质,它只是系统的一个工具。
用户界面shell(还有其他用户界面如kde等图形界面)-->内核--》硬件。

2、shell的种类
/bin/sh
/bin/bash  默认shell
/bin/ksh   兼容bash
/bin/tcsh  c shell
/bin/csh   已被tcsh替代,c shell
可以在/etc/shells文件中查看有哪些shell种类, 以下我们要学的都是bash这个shell的知识.


3、bash shell使用环境

1、登录消息显示数据      
(1)终端登录显示信息   /etc/issue
(2)所有用户登录显示信息  /etc/motd
(3)环境文件设置:
/etc/sysconfig/i18n    //设置语言
/etc/profile           //设置几个重要环境变量
/etc/bashre            //确定umask的功能


二、shell的基础操作

1、TAB      指令和文件补全,连按两次会把未写完的指令或文件名都列出来。
2、alias  别名和unalias  取消别名

        我们可以通过alias把一个常用的并且很长的指令别名一个简洁易记的指令。
        如果不想用了,还可以用unalias解除别名功能。
        直接敲alias会看到目前系统预设的alias

例: alias lm ='ls -al|more'    //以后就可以用lm命令代替这个命令了。

3、history 记录命令历史, 用向上键或向下键切换上一条命令或下一条命令。

4、通配符

*             //匹配文件中的任何字符串
?            //匹配单个字符串
[......]      //匹配方括号内的任何字符串   例: ls log[1-9] 显示文件夹下log开头以数字1到9结尾的所有文件,可能会显示如:log1 log8  log4。
[!.....]      //取反操作,即匹配不是方括号内的任何字符串


5、常用符号


“”          //双引号,可引用除字符$(美元符),  \(反斜杠),`(反引号)外的任意字符。且双引号中的$号仍能代表变量。  \后面是普通字符表示换行,如\后面是特殊字符就表示转义。
''            //单引号,里面所有的内容全为字符,包括$也变成字符,不再表示变量。
、、          //反引号,位于键盘的Tab键的上方。用于把系统命令输出到变量。如: #shijin=The date is `date`,即把data这个系统命令执行的结果输出给shijin变量。#echo $shijin 显示结果为 The date is 2011年 03月 14日 星期一 21:15:43 CST
\             //脱意符,即把后面的特殊字符转换为普通字符如\*,此时*就只是个星号,而不是代表任意字任的意思了。如果后面是普通字符,如123等普通字符就是换行。
#             //注释
;            //连续命令分隔符
 
~             //用户主目录
&             //命令后台执行

6、快捷键

ctrl+c        终止当前命令
ctrl+d        输入结束
ctrl+s        暂停屏幕输出
ctrl+Q        恢复屏幕输出
ctrl+u        在提示符下删除整行命令
ctrl+z        暂停当前命令

三、输入输出

(一)几个命令

echo命令   //显示文本行或变量。或把字符串输入到文件
    例: #echo this is a monitor  //显示一段文本。结果就是: #this is a monitor
        #echo $PATH   //显示变量的值。

cat        //显示文件内容,创建文件。
   例: #cat 1.txt   //显示1.txt文件中的内容。
        #cat >1.txt  //建一个1.txt文件,并可以为1.txt添加内容。按ctrl+c结束输入。

read[-tp] 变量名        //从键盘或文件的某一行文本中读入信息,并将读到的值赋给一个变量。当有多个变量时,输入的值将以空格分开按顺序分别赋值不同的变量。

-p:后面会显示提示的字符。
-t:等待输入的秒数  

 例:#read var1 var2     //读两个值赋给变量 var1  var2,然后会出现输入提示。
        this is             //var1的值为this  var2的值为is

read -p "please enter you user" user   //输入此命令后会有输入提示,输入的内容将赋值给user变量。
如果此是用户输入了 Khp  ,那么echo $user  的值会为 khp

read命令一般用于人机交互,如可以要求用户输入帐号,密码等,然后把这个变量用在脚本中引用等。



(二)重定向

1、系统设定三种默认传输:
代码0  为标准输入  ,标准输入设备一般为键盘,鼠标,硬盘等。
代码1  为标准输出, 标准输出为显示器。
代码2  标准错误输出。

2、重定向输出:
>     重定向输出,覆盖输出,即如果输出对象中已有内容,将被覆盖。
>>    重定向输出,但追加输出,即把输出的内容追加输出对象已有内容的后面。
2>    重定向标准错误输出。即只输出错误的信息。覆盖输出。
2》   重定向标准错误输出。即只输出错误的信息。追加输出。

     例:ls /root > 1.txt   //把root文件夹下的文件都重定向输入到1.txt中。
         ls /root/1.tx 2>>1.txt  //因为root目录下没有1.tx这个文件,就会显示错误信息,会把错误信息存到1.txt文件中。
         ls /root/1.txt >>1.txt 2>>2.txt  //把命令执行的正确信息存放到1.txt下。把命令执行时的错误信息存到2.txt下。
         ls /root/1.txt >>1.txt 2>>1.txt  //可以把正确信息和错误信息放于同一个文件中。

&>   把命令执行的正确和错误信息存于同一个文件中。
例:ls /root/1.txt &>1.txt     ls /root/1.txt >>1.txt 2>>1.txt   这两条命令执行结果一样。

3、重定向输入

<     重定向输入
<<    重定向输入 分界符   //从标准输入中读取数据,直到遇到分界符的内容即退出输入。

      例:#sort <1.txt   //把1.txt文件中的内容排序后显示出来。
          #sort <1.txt>2.txt  //把1.txt中的内容排序后,输出到2.txt中。

(三)管道

1、 |  把前一个命令的输出,当后一个命令的输入。

例: ls -al /etc |less      //把etc文件夹下的内容显示出来,然后同less命令进行分页显示。    


2、tee 双向重定向。 从标准输入读取数据,并把输出的内容同时显示到标准输出屏幕上,并且也同时存于别一个地方。
-a 即是追加到文件中,不加就是覆盖。

  例: ls /etc |tee -a 1.txt   //把ls命令的执行结果输出到屏幕的同时,存一份到1.txt中,且是追加方式, 不覆盖1.txt中的原有数据。



四、命令执行顺序

1、&&

command1 && command2   //当命令1执行成功后,才能执行命令2.前面的command1执行不成功,后面的command2不执行。

2、||

command1 || command2  //当command1命令执行不成功,就执行command2命令。command1命令执行成功的话,就不执行command2。

3、()

(command1;command2;command3;......)  //加上括号的组合命令,将按顺序执行命令。

4、{}
{command1;command2;command3;.....}  //每一个命令单独在一个子shell中独立执行,而不是作为一个整体依次执行。


五、字符操作(合并、切割)
1、cut
且来从标准输入或文件文件中剪切抽取字符或域(即字段,一般是用TAB键把一段文本分为多段)。以行为单位。如果有很多行,将把所有行的都剪切下来。

cut [-cfd] file1 file2

-c 指定剪切的字符数
例:khp kuanghuaping  male
    sj sujun          female

 存于test.txt中。
例:
cut -c 4,6-7 test.txt  //剪切test.txt中所有行第4和6到7个字符,空格也算字符。所以此处会显示:  
 ua //第一行的第4个是空格
suj

-f 剪切的域数,即段数。一般用TAB键把一段文本分为多段。

cut -f 3 test.txt    //这里剪切第3段,即  
male
female

注意:有些不支持空格作为分段。只支持TAB分段。

-d 一般和-f一起使用,即指定用什么字符来分隔文本成段,默认是空格或TAB,也可以手工指定。

 echo $PATH |cut -d : -f 3  //用冒号作为文本的分段符,剪切第三段文本。

cut -d" " -f 1 test1.txt   //以空格作为分段符。


2、paste
cut是从文件中抽取内容。paste也是从文件中抽取内容。类似于联合两个文件中的字段。
paste [-ds-] file1 file2
-d 手工指定文本的分隔符,不用默认的空格和tab.
-s 将每个文件合并成行,而不是按行粘贴。
-  使用标准输入

例1:
test.txt内容:
khp kuanghuaping  male
sj sujun female

test1.txt内容:
hubi yc
hena zz

#paste test.txt test1.txt
显示结果
#khp kuanghuaping  male hubi yc
 sj sujun female hena zz

例2:
paste -d: test.txt test1.txt   //两个文件中的字段用冒号分隔。

khp kuanghuaping  male:hubi yc
 sj sujun female:hena zz

例3:
paste -s test.txt test1.txt  //同一个文本文件中的所有行都拼成一行显示。

khp kuanghuaping  male  sj sujun female
hubi yc hena zz

例4:

ls/etc | paste -d" " ----    //etc目录下的文件以空格为分格符,分4列显示出来。 有些不支持此选项。
类似于联合了两个文本。


3、join
连接两个文件中的内容。类似于sql的连接,可以连接两个文件中的相同部分,也可以连接不同部分。


join[option] file1  file2

 -a FILENUM:除了显示匹配好的行另外将指定序号(1或2)文件中不匹配的行显示出来
   -e EMPTY:将需要显示但是文件中不存在的域用此选项指定的字符代替
   -i :忽略大小写
   -j FIELD :等同于 -1 FIELD -2 FIELD,-j指定一个域作为匹配字段
   -o FORMAT:以指定格式输出
   -t CHAR :以指定字符作为输入输出的分隔符
          join 默认以空白字符做分隔符(空格和\t),可以使用 join -t $'\t'来指定使用tab做分隔符
   -v FILENUM:与-a相似 但值显示文件中没匹配上的行
   -1 FIELD:以file1中FIELD字段进行匹配
   -2 FIELD:以file2中FIELD字段进行匹配

例1:
1.txt
khp kuanghuaping  male
sj    sujin      female
sc     lichen     male
sj     suko      female

2.txt
khp hubei  yc
sj  henan  zz
cw  beijin tz
(1)默认连接
join 1.txt 2.txt    //连接两个文个中域0相匹配的行进行连接,匹配的域0只显示一次。
默认是以域0(即第1域)进行匹配,域0即第一个字段。连接并显示匹配的字段。如果有多个相匹配的行,但匹配字段不是相邻行时,只连接第一次出现的行。
khp kuanghuaping male hubie yc   
sj sujin female henan zz

而  sj suko female 此时当中隔了一行,就不做连接显示,如果这两行挨着,就会显示。

(2)手工指定相同域段进行匹配连接
join -j 1 1.txt 2.txt   //手动指定域,以两个文件的第1域作为匹配域。和上面的结果一样。

(3)手工指定不同域段进行匹配连接。

join -1 4 -2 3 1.txt 2.txt   //以第1个文件中的第4个域与第2个文件中的第3个域作为匹配字段。

注:连接域字段相邻且匹配时,两行数据都会显示出来。但如果匹配字段不相邻,隔行后,只相连第一个匹配的行。剩下的即使匹配也不连接显示。

(4)-a同时显示不匹配的行。 -a1表示第一个文件,-a2表示第二个文件。
join -a1 a.txt b.txt
显示如下:
khp kuanghuaping male hubie yc   
sj sujin female henan zz
sc     lichen     male    //第1个文件中不匹配的行也显示出来在后面。
sj     suko      female

(5)-o 选择性连接

join -o 1.1,2.2 1.txt 2.txt     //只显示第一个文件中的第一列和第二个文件中的第二列。
即按默认匹配后,只显示1.txt中的第1个字段,和第2个文件中的第2个字段,1.1,2.2中间用逗号分隔。
结果如下:

khp  hubie   
sj  henan


4、split

分拆文件,即把一个大的文件按大小,或按行数分割成多个文件。
split [-bl] file outfile  

-b:按大小分割,后面是指多少K大小。
-l:按行数,即多少行分割一个文件。如果省略-b  -l参数,将默认以1000行为标准分割文件。

file:要分割的大文件的文件名
outfile:分割后的小文件的文件名前缀,不指定的话默认为xaa  xab  xac排列下去。

例:

split -b 1024 bigone.txt   smfile  //把bigone.txt按每1024K大小分割成一个小文件,小文件名前缀以smfile开头。


6、tr
删除一个文件或标准输入中的某个字符、字段,或对某个字符、字段进行替换。

tr[-d s c] [字符串1][字符串2] file1 file2 .....

-d:删除某个字符。
-s:删除所有重复出现字符序列,只保留第一个
-c:用字符串1中字符集的补集替换此字符集,要求字符集为ASCII
字符范围:

指定字符串1或字符串2的内容时,只能使用单字符或字符串范围或列表。
[a-z] a-z内的字符组成的字符串。
[A-Z] A-Z内的字符组成的字符串。
[0-9] 数字串。
\octal 一个三位的八进制数,对应有效的ASCII字符。
[O*n] 表示字符O重复出现指定次数n。因此[O*2]匹配OO的字符串。
tr中特定控制字符的不同表达方式
速记符含义八进制方式
\a Ctrl-G  铃声\007
\b Ctrl-H  退格符\010
\f Ctrl-L  走行换页\014
\n Ctrl-J  新行\012
\r Ctrl-M  回车\015
\t Ctrl-I  tab键\011
\v Ctrl-X  \030

\040      空格

例:

tr -s "[a-z]"result.txt //去除result.txt里面的重复的小写字符

tr -d '\0' <1.txt   //删除1.txt中的所有空字符。'\0'可写成"[\0]"

cat a.txt |tr "[a-z]" "[A-Z]" >b.txt  //把a.txt中的所有小写字母转换成大小的,并存到b.txt中。

tr -cs "[a-z][A-Z]" "[n]" <1.txt   //把1.txt中所有非字母的字符全删除。即非 "[a-z][A-Z]"的字符全删除,注意这两个集合是在一个引号内的,没有分开。

tr -s "[\r]" "[n]" <1.txt            //把1.txt中的所有tab键换成空格键。


7、sort


对文件进行排序
sort[-k u r m t b f c] file  [-o outfile]

-k:按哪个字段排序,默认按0域进行排序。
-u:就是uniq,重复的行仅显示一行,但与uniq的区别在于,sort不管你相同的行相不相邻,都算作重复行。
-r:反向排序
-t:设定不同的分隔符,默认是TAB
-b:忽略文件前面的空格部分。
-f:忽略大小写差异
-c:测试文件是否已分类,分类则不返回信息,不分类则反回信息。
-o outfile:把排好序的文件存入到哪个文件,类似于重定向。
-n:指定为数值类型,如1,2,3,4,5,6,7,8,9,10,11,如果不指定数值类型,那么11会排到2的前面。

例:2.txt
banana:30:5.5
apple:10:2.5
pear:90:2.3
orange:20:3.4

sort -t: -k2 -n 2.txt  //以冒号作为行的分段符,并以第二段的值来排序,且第二段的值是数值类型。
apple:10:2.5
orange:20:3.4
banana:30:5.5
pear:90:2.3


8、uniq
删除重复行或禁止重复行。uniq的重复行的标准是相邻的重复行,要求没有间隔的。有间隔的都不算重复行。这是与sort -u的区别。

uniq [-u d c f] file

-u:只显示不重复的行。
-d:只显示有重复数据行,每种重复只显示一次。
-c:显示每一重复行出现的次数。
-f:(或-n) 前n个域被忽略。

例:1.txt全文:
test
test
my
test
123
123
456


uniq 1.txt
结果:
test
my
test
123
456

uniq -u 1.txt
结果:
my
test
456

9、wc
计算文本的数据,如有多少行,多少字符。

wc[-l w m] file

-l:显示有多少行
-w:显示有多少字,如是英文则一个单词表示一个字
-m:显示多少字符,如是英文,每个字母就是一个字符。

10、find


11、xargs



六、正则表达式



(一)基本字符集及含义

1、^(6键上档键):只匹配行首
2、.(点):只匹配单个字符,是任意单个字符。(除NUL)。
3、$:只匹配行尾。
4、*:能匹配前面的字符零次或任意次,是表示匹配次数的。例: zo* ,可以匹配zo,zoo,zoooo,z(即匹配前面的字符0次),等价于zo\{0,\},o字符至少出现一次。
      .* 组合,表示任意长度的任意字符。a.*b,即a开头,b结尾的任意字符串。amnb  ab  aab都匹配。
5、[]:匹配括号内字符范围。
6、\:去意符,即把特殊字符转换为普通字符。
7、pattern\{n,m\}:即pattern出现n到m次。例:  (AC)\ {3,5\}B,即A出现3到5次,即ACACACB,ACACACACACB都匹配。
8、pattern\{n\}:即pattern只出现n次。例: A\{3\}B,即AAAB。
9、pattern\{n,\}:即pattern至少出现n次。 例:A \{3,\}B    ,即AAAB,AAAAAAAAAB都匹配,只要A至少有3个即可。
10:\< 或\b :其后面的任意字符必须作为单词首部出现。例: grep "\<root" /etc/passwd 找单词首部有root的行。grep "\broot" /etc/passwd一个意思。
11:\> 或\b:其前面的任意字符必须作为单词首部出现

grep "\<root\>" /etc/passwd   精确查找含有root单词的行。
12、  \(\):分组。 \(acd\)  把acd当一个整体。 要重复也是acd一起重复。
---------
扩展的正则表达式字符及其意义,只能用在egrep中:
+:匹配前面的字符一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo"“zoooooo",但不能匹配 "z"。+ 等价于 zo\{1,\},即o至少匹配1次。
?:匹配前面的字符零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 do(es)\{0,1\}。
():表示一个字符集合或用在expr中。
|:表示或,匹配一组可选的字符。
(二)grep和egrep

gerp [option]  '正则表达式' [文件]

option:选项
正则表达式:要搜索的字符
文件:指从哪个文件中搜索。

-a:在二进制文件中,以文本文件的方式搜索。
-c:只输出匹配行计数,即搜索到匹配的次数。
-i:不区分大小写
-n:显示匹配的行号
-v:取反。显示不匹配的文本的所有行。
-h:查询多文件时,不显示包含匹配字符的文件名。
-l:从多个文件中搜索时,只显示包含匹配字符的文件名。
-s:不显示不存在或无匹配文本的错误信息。






六、变量类型

1、本地变量

(1)作用域:整个脚本进程有效。只在当前用户shell下有效,子shell下也是无效的。
        切换用户,或同一用户下的不同shell,或子shell下都无效。关闭shell就会消失。

(2)变量的定义,查看和撤消

定义一个变量:

     变量名=变量值
      例: name=khp  
      也可以: set name=khp   //只是大多数时候set省略了。

查看一个变量值:
echo $name   //查看变量name的值。也可以是echo ${name},花括号大多数情况下可以省略。


引用变量:

$变量名   或  ${变量名}

撤销变量:

unset 变量名  //撤消一个变量。

查看所有变量:

set   用set命令查看所有的本地变量。



2、局部变量

作用域:只能当前代码段有效,同一shell中的不同代码段都不能引用。

local VARNAME=VALUE   //加关键字local,很少用。


3、环境变量

作用域:当前用户shell和子shell下有效。就算同一用户名,不同的shell下也无效。  用bash命令打开子shell

定义方法:
(1)export VARNAME=VALUE  //加关键字export

(2)VARNAME=VALUE         //定定义成本地变量。
     export VARNAME        //也可以先定义为本地变量,然用后关键字export把本地变量转换为环境变量。

环境变量的几个命令:
env :查看环境变量

export :查看哪些变量是由本地变量转换为环境变量的。

有导出功能。


4、位置变量

(1)普通位置变量

脚本中可以用位置变量。然后在执行脚本时,在脚本后面给这些位置变量赋值。位置脚本不能超过9个。
$0 $1 $2 $3 ......$9   //其中$0是脚本名。

例:
    #touch test.sh      
    #vim  test.sh
    
 脚本编号:
#!/bin/bash    //脚本中必须有的,指示脚本用哪个脚本程序执行,执行脚本程序的位置。
#test          //脚本描述

echo "这个脚本的名称是:$0"
echo "这个脚本的第一个参数值是:$1"
echo "这个脚本的第二个参数值是:$2"

脚本执行:

#./test.sh  first second     //给脚本的位置变量赋值,用空格间格。

执行结果:

这个脚本的名称是:test.sh
这个脚本的第一个参数值是:first
echo "这个脚本的第二个参数值是:second

(2)位移位置变量

shift[n]   //参数向左位移n位。

在脚本中每shift一次,参数向左位移一次。位移后,被位移的参数从参数表中删除。

例: shift.sh
#!/bin/bash
#
echo this is $1
shift
echo this is $1
shift 2
echo this is $2


调用:
./shift.sh 1 2 3 4 5

结果:
this is 1     //第1个参数为1
this is 2     //echo this is $1,如果没使用shift,此时的$1应为1,但shift是把所有参数向左位移了一位,且被位移的参数值直接从参数值列表中删除了,即1已经不在参数值中了,只有2,3,4,5了,所以2变成了第1个参数的值了。
this is 5     //shift 2,即把参数值向左位移两位,因现在参数值列表中只有2,3,4,5,所以位移两位后,参数值列表就只有4,5了。此时第二个参数值为5,所以此处显示为5.




5、特殊变量

$#    //返回脚本中脚本参数的个数。如把$#插入到脚本中,那么执行时,此位置将显示脚本中使用的参数的个数。

$?    //显示上一个命令执行后的状态。是状态而不是结果。0表示执行结果没有错误,其他任何值都表示有错误。可以作为判断条件来使用。

$$    //脚本运行的当前进程ID号。

$@   //与$#相当。

$-   //显示shell使用的当前选项

$!   //后台运行的最后一个进程的进程ID号。
 
$*   //以一个单字符串显示所有向脚本传递的参数,与位置变量不同,此参数可超过9个。


七、条件比较和逻辑关系
1、整数比较
[ num1 比较条件 num2 ]   //中括号与数字间一定要有空格。
test 比较条件             //也可以比较

-eq  :数值相等,则为真,不相等就为假。
-ne  :两数如不相等,则为真。两数相等为假。
-gt  :大于则为真,否则为假。
-lt  :小于则为真,否则为假
-ge  :大于等于为真,否则为假
-le  :小于等于为真,否则为假

例:
 

#num1=120
#[ $num1 -eq 120 ]
#echo $?
#0

2、字符串比较
[ string1 比较运算符 string2 ]

=     两字符串相同为真。
!=   两字符串不相同为真
-z    空字符串为真。
-n    非空串为真
>     大于字符长度为真
<     小于字符长度为真

例:
#export num    //定义一个环境变量,但没有赋值
# [ -z $num ]  //测试此环境变量是否为空。空则为真。
#echo $?       //结果为0,表示为真。
#0

3、文件状态测试

[ 状态符 文件名 ]

-d  文件是否是目录,是就为真。
-r  文件是否可读,可读为真
-w  文件是否可写,可写为真
-x  文件是否可执行,可执行为真
-L  文件是否是符号链接,是为真
-s  文件长充大于0,非空为真。
-f  是否为正规文件,正规为真。
-u  文件有suid设置为真。

例:
#[ -w 1.txt ]    //1.txt是否可写,可写即为真。
#echo $?


4、逻辑关系

&&  逻辑与    -a
||  逻辑或    -o
!  逻辑非

例:

#! id khp &> /dev/null && useradd khp   //id命令查询khp这个命令是否存在,如果存在,则为真了,即有用户名存在就为真了,所以要在前面加上!,即用户不存在才为真,那么执行与后面的添加用户命令。

5、算术运算的办法
A=6
B=9

let算术表达式      C=$A+$B    
$[算术表达式]      C=$[$A+$B]
$((算术表达式))   //双小括号

6、expr用法

expr一般用于整数值,也可以用于字符串。是一个手工命令行计数器。

expr  元素 操作符  元素  //一般格式

(1)四则运算,即加减乘除的运算。

expr 10 + 10   //数字与加号之间要有空格
结果为20

expr 10 % 3   //求余
结果为 1

(2)数值测试。可以用expr测试一个数,因为当expr计算的是一个非整数时会返回错误。

 #rr=3.14
# expr $rr + 3
expr: 参数数目错误    //如参数中不是一个整数会报错。所以可以用来测试一个参数的值是不是整数。
# rr=3
# expr $rr + 3
6

(3)增量计数

loop=0   //变量赋初值
loop=`expr $loop + 1`  //一定要加反引号,即表明反引号中的所有内容作为一个命令的整体运行,expr 会作为命令,  $loop 会作为变量的引用, + 1会作为算术运算。结果为 1

c=`expr $A + $B`  //也是一种算术运算

下面讲一下双引号和单引号与反引号之间的区别。
双引号的区别:
loop="expr $loop + 1"   //只会把$loop作为变量引用,其他作为字符。
echo $loop
expr 1 + 1

单引号:
loop=‘expr $loop + 1’    //单引号里的所有内容作为字符串。
echo $loop
expr $loop + 1


(4)模式匹配
#cc=myname.doc
#expr $cc : '.*'   //.(点)代表任意单个字符,*表示任何字符,即贪婪模式,匹配最多的字符。但这里的变量中的字符串中不能有空格,否则会出错,即如果 cc="my name.doc" ,则会出错。
6
 



八、语句

1、if then else  语句

     if (条件1)
     
     then 命令1
   
       elif  条件2
       then  命令2
     
     else  命令3
     fi                     //用fi结尾

如果条件1为真,则执行命令1,然后跳出if语句,如果条件1不成立,那么判断条件2是否为真,如为真则执行命令2,如不为真,则执行命令3.



2、case   
 //如果变量值与模式1中的值匹配,那么执行模式1中的命令。并不再与后面所有的模式进行匹配。如果模式1不匹配,则按次序与下面的模式条件进行匹配。即匹配一个后,后面的将不再进行匹配,跳出。

case 变量值   in


模式1)

     命令1
     命令2
     ......
     命令n
      ;;        //模式之间用两个分号隔开
模式2)

     命令1
     命令2
     ......
     命令n
     ;;
esac


3、for循环

 //如果变量的值 在后面的列表值中,就执行下面的do。要多个循环,列表值就要加多个值。

for 变量名  in  列表值

do  

     命令1
     命令2
     ......
     命令n

done



4、until循环

//until循环至少执行一次,即先执行do后面的命令,执行完后再判断条件,如果条件为真,继续执行do后面的语名,如果不为真则跳出循环。


until 条件      
do
   
     命令1
     命令2
     ......
     命令n

done


5、while循环

//先判断while后面的条件,如果条件为真,继续执行do后面的语名,如果不为真则跳出循环。
while 条件      

do
   
     命令1
     命令2
     ......
     命令n

done


6、break 和contiune

break 跳出整个循环语句,即使多层嵌套也全部跳出。
contiune 跳出本次循环。接着执行下次循环。


九、函数

1、函数的定义

函数名()

 {
命令......
 }


2、函数文件的创建

与脚本文件格式一模一样。一个函数文件中可以定义多个函数。


3、函数的调用:

(1)调用在脚本中的函数

用函数名即可调用。但函数的定义一定要函数调用之前。函数中可以使用参数。


(2)调用脚本外的独立函数文件

在绝对路径前加.(点)来调用独立函数文件
在脚本的开始部分用绝对路径把这个函数文件导入进来。 ./var/shell/adduser.sh
然后在脚本中就可以直接用函数文件中的函数名来调用函数了。一个函数文件可以定义多个函数。

(3)函授载入检测
 ./var/shell/adduser.main
set

//在shell中载入函数文件名下面用set命令即可查看是否已载入。


(4)函数的删除

unset命令删除函数。
在定义好的函数下用unset 函数名
或在包含进的函数文件名下用unset命令,都可以删除函数,即不使用函数,函数没有真的没删除。


4、参数的传递

详见位移变量。


5、函数的使用

1、`函数名`   :用反引号引起函数名,即表示函数的执行结果。可以把函数的执行结果赋值给变量。

十、脚本调试

sh[-nxv] 脚本名

-n:不执行脚本,仅查脚本的语法问题。
-x:将脚本的内容显示到屏幕上,且将每一步的执行结果也显示出来。
-v:执行脚本前先将脚本的的内容辆出到屏幕,到最后执行脚本,且将脚本的执行结果显示出来。



十 一、sed

1、概述
(1)sed是一个非交互性文本流编辑器,它编辑文件或标准输入导出文件的拷贝。注意只是拷贝,sed并不与原文件打交道,它只是操作原文件或标准输入的一个拷贝,然后用命令改动,再重定向到一个文件或输出到屏幕。
(2)sed 是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。
(3)vi也是文本编辑器,但是是交互性的。

2、sed的几种使用方式:


sed [option]  'AddressCommand'   files......

option:
  -e:直接在命令行上运行sed操作,并且可以运行多脚本。如: sed -e script -e script 。我们把一条完整的sed语句叫sed脚本。
  -n:静默模式,不再默认显示模式空间中的内容,只有经过sed处理的行才显示出现。
  -f:执行sed脚本文件。 sed -f /home/khp/sed.script  即把sed命令一行一行的写到了sed.script文件中了,然后用sed -f 命令去读取这个脚本文件。
  -i:直接修改原文件,而不是修改拷贝。  
  -r:可以在sed命令中使扩展正则表达式。

Address:一般为行号或模式
    x:x为行号,如2,即第2行。
    x,y:行号范围,如,2,8即第2到8行。
    /pattern/:模式匹配,包含pattern字符串的行。如,/disk/ 即所有包含 有disk字符串的行。
    /pattern1/pattern2/:同时包含pattern1和pattern2的行。要都包含。
    /pattern1/,/pattern2/:第一次匹配pattern1字符串的行,到第一次匹配pattern2的行之间的所有行。两次匹配行之间的所有行。
    $:最后一行。
    x,+N:从第x开始,向后N行。5,+6,第5行开始向后的6行,全匹配。
    x,y!:不匹配x和y行的所有行。例,4,8!即4到8行外的所有行。


command:
  p:显示,打印匹配行到屏幕。例: sed '1,$p' test.txt   显示出test.txt中第一行到最后一行的所有内容。
  a:新增,在指定行后附加文本,会出现在当前行的下一行。
      a\string:将字符串添加到指定行后。   sed '5a\this is append' test.txt  把字符串this is append追加到第5行后面。
  i:插入,插入字符到定位行,但会在定位行的上一行出现。
  c:替换,c后面可接字符串,替换指定行或行与行之间的内容。
  d:删除,删除定位行。
  s:搜索,查找并替换,不仅可搜索,还能替换,一般与正规表达式一起使用。
      sed 's/khp/kuang/gi' /home/khp/test1  查找test1中包含khp的字符串,用kuang替换。g为全文替换,不加的话,只替换每行中第一个匹配的字符串。i为忽略大小写。
      sed 's/khp/$boy/p' /home/khp/test1  查找到test1中的khp字符串,在前面加上字符串boy。
      sed 's/khp/boy$/p' /home/khp/test1  查找到test1中的khp字符串,在后面加上字符串boy。
  r:读取,将指定文件的肉容添加到符合条件的行处,即从另一个文本中读取内容添加到本文件中的匹配行后面。 sed '2,8r /home/khp/test1' /home/khp/test2  把test1中所有的内容添加到test2文件中第2到8行后面,2到8行每行后都添加一次。
  w:写入,将地址指定的范围内的内容另存至指定的文件中。 sed  -n '/khp/w /home/test2' /home/test1  把test1中含有khp字符的行添加到/home/test2中。
  =:显示行号,sed -n '/^$/='  a.txt  显示a.txt中的空白行号。