shell
   通常,替我们工作的是硬件,而控制硬件的是核心,用户是利用shell控制一些内核提供的工具,来控制硬件替我们正确工作。进一步说,由于内核听不懂人类语言,而人类语言也没办法直接记住内核的语言,所以两者沟通就要通过shell来支持了。Shell是包含一系列可执行的命令或声明的文本文件。
   Shell有不同的版本,如Bourne  SHell(sh),在sun中默认的C SHell,还有K SHell,还有TCSH等,Linux使用的是这一版本Bourne Again SHell(简称bash)
Bash  shell 中的变量
本地变量:如 #name=donne   #echo ${name}; 只对本地shell有效,不对子shell有效。其中这个{}有时可以省略的,但是有时不可以,如:#TIME=${date +"%H:%M:%S"}
                                                #echo $TIME
环境变量:如:export NAME,即对本地shell有效也对子shell有效
预定义变量:(位置变量)  $0,1,...9
特殊变量:$?     
Shell 脚本的用途:自动化常用的命令,执行系统管理和故障排除,创建简单的应用程序
     处理文本或文件。
创建shell脚本:
第一步:使用vi这类的命令来创建一个包含命令的文本文件,其中第一行必须包括shebang序列:如#!/bin/bash  -   用于bash脚本(在Linux中最常见)
           #!/bin/sh    -    用于Bourne shell (在uinix类型的系统上最常见)
           #!/bin/csh   -    用于C脚本(在BSD衍生的系统上最常见)
           #!/usr/bin/perl  -   用于Perl脚本(一种高级的脚本和编程语言)
        给脚本加注释,#符号后面的内容都被认为是注释。
第二步:使脚本可以执行:#chmod u+x myscript.sh
        要执行这个新脚本,把脚本放在你的可执行路径中,或者在命令行上指定脚本   
        的绝对路径或相对路径。
     如:
我们可以用命令: bash  -n   XX.sh  来查看语法的正确与否。
我们可以用   bash   xx.sh来执行这个脚本。
进行算术运算:三种方法
a=1
b=2
let d=$a+$b
echo $d
e=$[$a+$b]
echo $e
f=$(($a+$b))
echo $f
   
    执行此脚本#./calc.sh
     注意:执行脚本使用了./calc.sh而不仅仅是calc.sh。为了只使用文件名来执行脚本,  
  它必须位于你的PATH中包括的目录中。#echo  $PATH
  因为你的脚本不在你的PATH中,你就必须明确它的位置,否则bash就不知道你指的是哪 
  个文件,因为总指向当前目录,你可以使用./calc.sh而不是~/calc.sh来运行脚本了。 
  多数用户把他们的脚本保存在~/bin目录中,这是因为该目录是默认PATH的一部分。
标准I/O和管道
Linux给程序提供了三种I/O频道
标准输入(STDIN)-  默认接受来自键盘的键入
标准输出(STDOUT)- 默认输出到终端窗口
标准错误(STDERR)-  默认输出到终端窗口
Linux的一个重要特性是它具备把命令的输入,输出和错误数据重新导向的能力。一般 
来说,这使程序的输入可以来自任何来源,输出可以转动任何目的地,除此之外,一个
命令的输出还可以直接成为另一个程序的输入。
把输出重新导向到文件
STDOUT和STDERR可以被重导向到文件:
支持的符合操作:
>  把STDOUT重导向到文件
2> 把STDERR重导向到文件
&> 把所有输出重导向到文件
文件的内容被默认覆盖。>> 会在文件内容的后面追加。
例如:find /etc -name passwd  >  find.out
      find /etc -name passwd  2>  find.err
重导向某个程序的STDERR意味着你只能看到它的输出。如果你知道命令会生出些错误但是你不介意也不想知道,就像以上命令一样,在这种情况下重导向标准错误就很有用。但是你真的不在乎这些错误,何必要保存在文件中呢?在这种情况下,你可以使用系统上的一个特殊文件:/dev/null。该文件是一个数据黑洞,发给该文件的内容全部忽略。
&>  重导向所有输出:
 # find  /etc  -name  passwd  &> find.all
2>&1   把STDERR重导向给STDOUT
   管道只能重导向STDOUT而不能重导向STDERR,如果想把所有输出都发送给管道
   命令,你就需要先把STDERR重导向到STDOUT,然后通过管道转发STDOUT
()   合并多个程序的STDOUT
   如  #( cal 2009 ; cal 2010 )| less
重导向多个目标(tee)
   #命令1 | tee 文件名 | 命令2
     把命令1的STDOUT保存在文件名中,然后管道输入给命令2
for 循环
   for  变量  in  值1  值2
   do
     使用$变量 的命令
     ... 
   done 
测试两个整数的大小:
   -eq (等于)  $A -eq $B    -gt(大于)   -lt(小于)  -ge(大于等于) 
   -le(小于等于)
查看文件内容(less和cat)
cat   由第一行开始显示文件内容。通过STDOUT可以显示一个或多个文件。
cat  -n  显示行号 ;  -A  显示所有字符,包括控制字符和非打印字符
less   一页一页的查看文件
    在查看时会用到:  /文本   搜索  文本
                      N/n 跳到上一个/下一个匹配的
    less和man相似  但less可以向前翻页
查看文件的部分截取(head和tail)
head  默认为显示前10行  -n  指定要显示的行数
tail  显示文件的最后几行,默认为10行   -n  指定要显示的行数
若要显示~/.bashrc的第11行到第20行。
   #head  -n  20  ~/.bashrc  |  tail -n 10
按关键字抽取文本(grep)
grep支持基本的正则表达式,不支持扩展的正则表达式;若想支持需加 -E
grep -i(不分大小写的搜索)  -n(来显示匹配的行号)   -v(显示不包含模式的行)
grep “root” /etc/passwd   
按列抽取文本(cut)
   cut  -d(来指定区分列的定界符【默认为TAB】);  -f(指定要显示的列); 
        -c(按字符切割)
   如 # ifconfig  |  grep “inet addr” | cut  -d:  -f2  | cut -d‘ ’ -f1
     192..168.0.46
     127.0.0.1
收集文本统计数据(wc)
     wc  计数单词总数,行总数,字节总数和字符总数
     wc  -l(计数行数)  -w(计数单词总数)  -c(计数字节总数)  
          -m(计数字符总数,不显示)
     如:  #ls  /tmp  |  wc  -l
           32
整理文本(sort)
     把整理的文本显示出来-不改变原始文件
      sort  -r(方向排序)  -n(使用数字大小排序,默认是以文字类型排序的)
            -f(忽略大小写的差异)  -u(就是uniq,相同的数据仅显示一行)
            -t(分割符)   -k(按那个字段来进行排序)
     如  #sort -t :  -k 3  -n  /etc/passwd
不显示重复行(uniq)
     sort  -u   从输入中删除重复行
     uniq   从输入中删除重复的前后相接的行
            -c(每行出现的次数) -d(只显示重复的行) -dc(显示重复了多少次)
            -u(只显示不重复的行)
如   #sort  userlist.txt  |  uniq -c
比较文件(diff)
   diff   比较两个文件之间的区别  
复制对文件的改变(patch)
   diff  命令的输出被保存在一种叫做“补丁”的文件中
   patch   命令复制在其他文件中进行的改变(要谨慎使用)
      使用-b来自动备份改变的文件
使用aspell来检查拼写
交互式检查文件中的拼写:#aspell check  letter.txt
非交互式的在STDIN中列举拼错的单词
  #aspell  list < letter.txt
处理文本的工具(tr和sed)
如#tr 'a-z' 'A-Z' < aa.txt   把aa.txt中的小谢字母都换成大写。
改变字符串(sed)
通常不改变源文件。
sed 的选项  -e 可以执行多个sed指令
如  #sed  '1,20s/line/Line/g  aa.txt
     要把在1-20行之间的line替换成Line,g表示全局替换。