Linux Shell 脚本攻略 
  第一章 小试牛刀 
  1.1 Shell发展的时间线 
早期计算机没有操作系统,也无图形化界面。 
20世纪60年代,支持交互式界面 
贝尔实验室,开发交互式用户界面,使得通过文本文件去执行程序,而非一堆命令。这些文件就是shell脚本,这带来了效率的巨大提升。 
早期Unix只支持一种交互式 shell 【sh】 
1989年,推出了一种全新的 shell 【bash】 
随着Linux的发展,bash 逐渐成为标准shell 
 
  1.2 终端中的显示输出 
  界面介绍: 
jacky@jacky-virtual-machine:~$
形式为:username@hostname$
$ 表示普通该用户,# 表示管理员用户root
 
  shell 脚本 
  打印 
echo  Hello worldecho  "Hello world ;world" printf  "%-5s %-10s %-4s\n"  No Name Markprintf  "%-5s %-10s %-4.2f\n"  1 Sarath 80.3456printf  "%-5s %-10s %-4.2f\n"  2 James 90.9989printf  "%-5s %-10s %-4.2f\n"  3 Jeff 77.564echo  -e "1\t2\t3" count=5 fruit=apple echo  "We have $count  ${fruit} (s)" 
 
输出:
Hello world ------------------------------- Hello world ;world ------------------------------- No    Name       Mark 1     Sarath     80.35 2     James      91.00 3     Jeff       77.56 -------------------------------- 1	2	3 -------------------------------- We have 5 apple(s) 
 
彩色打印: 
echo -e "\e[1;31m This is red text \e[0m" 
 
文字:重置=0,黑色=30,红色31,绿色=32,黄色=33,蓝色=34,洋红=35,青色=36,白色=37。
背景:重置=0,黑色=40,红色=41,绿色=42,黄色=43,蓝色=44,洋红=45,青色=46,白色=47。
 
  环境变量 
env  $ pgrep gedit   cat /prop/$PID /environ | tr '\0'  '\n'     var=1234567890 echo  ${#var} echo  $SHELL echo  $0 echo  $UID 
 
export 命令生命了将由子进程所继承的一个或多个变量,这些变量被导出后,当前shell脚本所执行的任何应用程序都会获得这个变量。
  1.5 Shell 进行数学运算 
  反引号的作用:存储命令 
#  存储命令 cmd_output=`ls | cat -n` echo $cmd_output 
 
在执行一条命令时,会先将其中的``中的语句当作命令执行一遍,再将结果加入到原命令中重新执行,例如:
date=`date -d '1 day ago'  "+%Y-%m-%d" ` echo  $date date=$(date -d '1 day ago'  "+%Y-%m-%d" ) echo  $date for  path in  `find $HADOOP_HOME  -name "*.jar" `do         export  HADOOP_CLASSPATH=$HADOOP_CLASSPATH :$path  done 
 
  整数运算 
使用let、(())和[]作为基本操作
no1=4; no2=5; let  result=no1+no2echo  $result let  no+=6let  no1++result=$[ no1 + no2 ]  result=`expr 3 + 4` result=$(expr $no1  +5) 
 
  浮点数 
echo  "4 * 0.56"  | bcresult=`echo  "$no  * 1.5"  | bc` echo  $result echo  "scale=2;22/7"  | bcno=100 echo  "obase=2;$no "  | bc echo  "obase=10;$no "  | bc echo  "sqrt(100)"  | bcecho  "10^10"  | bc
 
  1.6 重定向与追加模式 
echo  "This is a sample text 1"  > temp.txtecho  "This is a sample text 1"  > temp.txtls +   2 > out.txt 0 -- stdin (标准输入) 1 -- stdout(标准输出) 2-- stderr(标准错误) 
 
  1.7 数组与关联数组 
Bash支持普通数组和关联数组。普通数组以整数作为索引,后者使用字符串作为索引。
  普通数组 
array_var=(test1 test2 test3 test4) array_var[0]="test1"  array_var[1]="test2"  array_var[2]="test3"  array_var[3]="test4"  echo  ${array_var[0]}  index=3 echo  ${array_var[$index]} echo  ${array_var[*]} echo  ${array_var[@]} echo  ${#array_var[*]} 
 
  关联数组 
declare  -A ass_arrayass_array=([index1]=val1 [index2]=val2) ass_array[index1]=val1 ass_array[index2]=val2 echo  "${ass_array[index1]} " echo  ${!ass_array[*]} 
 
注:如果没有声明,则默认是数值索引数组。
 
  1.8 alias定义别名 
alias  install='sudo apt-get install' alias 
 
alias是暂时的,一旦关闭终端,别名就会失效,若要永久使用可以把定义语句写入~/.bashrc文件中。每当一个新的交互式shell进程生成时,都会执行~/.bashrc文件。
echo  'alias new_command="command sequence"'  >> ~./bashrc' 
 
创建别名时,如果已经有同名的别名存在,那么原有的别名设置将被新的设置取代。
  1.12 函数和参数 
  定义函数 
function  fname(){  	statements; } fname() {  	echo  $1 ,  $2 ;  	echo  "$@ "   ; 	echo  "$*"     ; 	return  0        ;  } fname  () { statement; }fname a  b 
 
读取外部输入:
输入参数 
说明 
 
 
$0 
脚本的名称 
 
$1 ,$2  ,$n 
第n个参数 
 
“$@” 
被扩展成"$1" , “$2”  , “$3” 
 
“$*” 
被扩展乘"$1c$2c$3" 
 
$? 
返回命令返回值 
 
 
建议使用$@,可以一个一个输出
 
  递归函数 
函数在编写的过程中可以调用自己,如下:
F  () { echo  $1 ; F hello; sleep 1 ; }
 
  导出函数 
$function  getIP  () { ifconfig $1  | grep 'inet' ; }$echo  "getIP ens33" >test.sh (base) jacky@jacky-virtual-machine:~/桌面$ bash test.sh test.sh: 行 1: getIP: 未找到命令 export  -f getIP(base) jacky@jacky-virtual-machine:~/桌面$ bash test.sh           inet 地址:192.168.6.129  广播:192.168.6.255  掩码:255.255.255.0           inet6 地址: fe80::d74:deb0:c82e:1f79/64 Scope:Link 
 
  向命令传递参数 
#! /bin/bash for  i in  `seq 1 $# `do  echo  $i  is  $1 shift  done  (base) jacky@jacky-virtual-machine:~/桌面$ bash test.sh a b c  1 is a 2 is b 3 is c 
 
shift命令将$1参数一次向左移动一个位置,让脚本使用$1访问每一个参数。
  1.17 比较与测试 
  条件语句 
if  condition;then 	commands; fi if  condition;then 	commands; else  if  condition; then 	commands; else  	commands; if 
 
if 和 else 语句能够嵌套使用。if的条件判断可能导致代码非常长,可以通过逻辑运算符将它变得简洁一些,如下:
[ condition ] && action   [ condition ] | |  action   
 
  算法比较 
[  $var  -eq 0 ] or [ $var  -ne 0  ] -gt  : 大于(greater than) -lt   : 小于(less than)  -ge : 大于等于 -le  : 小于等于 -a : 逻辑与操作符 -0 : 逻辑或操作符  [ $var  1 -ne 0 -a $var2  -gt 2 ]    
 
  文件系统相关测试 
[ -f $file_var  ]: 是否是一个正常的文件路径或者是文件名 [ -x $var  ]: 文件是否可执行 [ -d $var  ]: 是否是目录 [ -e $var  ]: 是否存在文件 [ -c $var  ]: 是否包含字符设备文件 [ -b $var  ]: 是否包含块设备文件的路径 [ -w $var  ]: 文件是否可写 [ -r $var  ]: 文件是否可读 [ -L $var  ]: 是否包含符号链接 
 
例子:
fpath="/etc/passwd"  if  [ -e $fpath   ] ; then 	echo  File exists ; else 	echo  Does not exits; fi 
 
  字符串比较 
[[ $str1  == $str2 ]]   [[ $str1  != $str2   ]]  [[    -z    $str1       ]]  [[    -n   $str1       ]]  
 
利用&&和||能够组合条件:
if  [[ $str1  == $str2 ]]  &&  [[ $str1  == $str2 ]] ;then 	commands; fi