louyaoluan 发表于 2018-8-24 06:50:51

shell复习摘要(一)

SHELL复习摘要(一)
  最近复习了shell,推荐一本书《Shell脚本学习指南》
  51cto下载地址:http://down.51cto.com/data/147424
替换运算符:
  ${varname:-word} 如果varname存在且非null,则返回它的值,否则返回word
  ${varname:=word} 如果varname存在且非null,则返回它的值,否则设置它为word
${varname:?message}如果varname存在且非null,则返回它的值,否则显示varname:message,并退出现在的命令或脚本。
  ${varname:+word} 如果varname存在且非null,则返回word;否则返回null。
  这里的冒号(:)都是可选的。如果省略冒号,则将每个定义中的“存在且非null”部分改为“存在”,也就是说运算符仅用于测试变量是否存在。
  例如:
  #!/bin/bash -
  g=
  a=${g:-"Hello World!"}
  echo $a
  f="Python"
  b=${f:+"C Program"}
  echo $b
  j=
  c=${j:="Perl"}
  echo $c
  l=
  d=${l:?"Error"}
  echo $d
  
  条件变量替换:
  Bash Shell可以进行变量的条件替换,既只有某种条件发生时才进行替换,替换
  条件放在{}中.
  (1) ${value:-word}
  当变量未定义或者值为空时,返回值为word的内容,否则返回变量的值.
  (2) ${value:=word}
  与前者类似,只是若变量未定义或者值为空时,在返回word的值的同时将
  word赋值给value
  (3) ${value:?message}
  若变量以赋值的话,正常替换.否则将消息message送到标准错误输出(若
  此替换出现在Shell程序中,那么该程序将终止运行)
  (4) ${value:+word}
  若变量以赋值的话,其值才用word替换,否则不进行任何替换
  (5) ${value:offset}
  ${value:offset:length}
  从变量中提取子串,这里offset和length可以是算术表达式.
  (6) ${#value}
  变量的字符个数
  (7) ${value#pattern}
  ${value##pattern}
  去掉value中与pattern相匹配的部分,条件是value的开头与pattern相匹配
  #与##的区别在于一个是最短匹配模式,一个是最长匹配模式.
  (8) ${value%pattern}
  ${value%%pattern}
  于(7)类似,只是是从value的尾部于pattern相匹配,%与%%的区别与#与##一样
  (9) ${value/pattern/string}
  ${value//pattern/string}
  进行变量内容的替换,把与pattern匹配的部分替换为string的内容,/与//的区
  别与上同
  注意:上述条件变量替换中,除(2)外,其余均不影响变量本身的值
模式匹配运算符:
  path=/home/tolstoy/mem/long.file.name
  ${variable#pattern}如果模式匹配于变量值的开头处,则删除匹配的最短部分,并返回剩下的部分。
  例:${path#/*/}返回tolstoy/mem/long.file.name
  ${variable##pattern}如果模式匹配于变量的开头处,则删除匹配的最长部分,并返回剩下部分。
  例:${path##/*/}返回long.file.name
  ${varuable%pattern}如果模式匹配于变量的结尾处,则删除匹配的最短部分,并返回剩下的部分。
  例:${path%.*}返回/home/tolstoy/mem/long.file
  ${variable%%pattern}如果模式匹配于变量的结尾处,则删除匹配的最长部分,并返回剩下的部分。
  例:${path%%.*}返回/home/tolstoy/mem/long
  这里的两种模式分别是:/*/,匹配任何位于两个斜杠之间的元素,.*匹配点号之后的接着的任何元素。
  POSIX标准化字符串长度运算符:${#variable}返回$variable值里的字符长度。
位置参数:
位置参数指的是shell脚本的命令行参数;同时也表示在shell函数内的函数参数。他们的名字以单个整数来命名。大于9时应该以花括号括起来。${10}
  $# 提供传递到shell脚本或函数的参数总数。
  $*,$@表示所有的命令行参数。
  “$*”以“$1 $2 $3”字符串形式表示所有的命令行参数。
  “$@”以“$1””$2”“$3”独立字符形式表示所有的命令行参数。会保留所有内嵌在每个参数里的空白。
  $?保存前一个命令的返回码
  $0保存程序或脚本名称
  set --改变位置参数($1,$2)。使用—的第一个参数来结束设置它自己的选项,则所有接下来的参数都会取代位置参数,即使它们是以正号或者负号开头。
  例如:
  $set -- hello “hi there” greetings设置新的位置参数
  $echo there are $# total arguments显示计数值
  there are 3 total arguments
     使用$*来传递参数
  使用$@来传递参数
   使用”$*”来传递参数
  使用”$@”来传递参数
  $shift截取一个参数
  
POSIX内置的shell变量
  $#   目前进程的参数个数
  $@传递给当前进程的命令行参数。置于双引号内,会展开为个别的参数。
  $*    当前进程的命令行参数。置于双引号内,展开为一单独参数。
  $-(连字号)       在引用时给予shell的选项。
  $?   前一命令的退出状态。
  $$   shell进程的进程编号(process>
  $0(零)       shell程序的名称
  $!    最近一个后台命令的进程编号。
算术运算符
  算数运算符都置于$((…))语法中。
  ++ --   增加及减少,可前置也可放在结尾
  + - !~   一元的正号、负号、逻辑与位的取反
  * / %      乘法、除法和余数
  + -加法与减法
  >   向左位移和向右位移
  <>=   比较
  == !=   相等和不等
  &    位的与
  ^   位的异或
  |      位的或
  && 逻辑与
  ||   逻辑或
  ?:   条件表达式
  = += -+ *= /= %= &= ^= = |=      赋值运算符
  算术运算符产生数字结果中,1表示真,0表示假。
  echo $((3 > 2))的值是1;$(( (3>2) || (4 0   在重定向或单词展开期间失败
  1-125   命令不成功的退出。特定的退出由于各自程序自己定义。
  126 命令找到了,但是文件无法执行
  127 命令找不到
  >128      命令因收到信号而死亡
  在脚本里可以通过exit命令传递一个退出值给它的调用者。
  exit 42
判断语句和逻辑NOT、AND及OR
  基本语法:
  if pipline
  
  then
  statements-if-true-1
  [elif pipeline
  
  then
  statements-if-true-2
  …]
  [else
  statements-if-all-else-fails]
  fi
  逻辑否
  if ! pipeline
  逻辑AND
  if pipeline1 && pipeline2
  逻辑OR
  if pipeline1 || pipeline2
  test命令
  他产生的不是一般的输出,而是可使用的退出状态。
  test有2种形式:
  lif test “$str1” = “$str2”
  lif [ “$str1” = “$str2” ]
  test表达式
  1)判断表达式
  if test(表达式为真)
  if test !表达式为假
  表达式1 –a 表达式2   两个表达式都为真
  表达式1 –o 表达式2   两个表达式有一个为真
  2)判断字符串
  string                            字符串不是null
  –n string            字符串的长度非零
  –z string            字符串的长度为零
  string1=string2      字符串相等
  string1 !=string2    字符串不等
  ==                     等于,在”[[”和”[”里行为不同,
  [[ $a == z* ]] 如果$a以”z”开头(模式匹配),那么将为true
  [[ $a == “z*” ]] 如果$a等于z*(字符匹配),那么结果为true
  [ $a == z* ] 文件通配符和单词切片
  [ “$a” == “z*” ] 如果$a等于z*(字符匹配),那么结果为true
  一点解释,关于文件通配符是一种关于文件的速记法,比如”*.c”就是,再如~也是,但是文件通配符并不是严格的正则表达式,虽然绝大多数情况下结构比较像。
  3)判断整数
  n1 –eq n2   整数相等
  n1 –ge n2   整数1大于等于整数2
  n1 –gt n2    整数1大于整数2
  n1 –le n2    整数1小于等于整数2
  n1 –lt n2    整数1小于整数2
  n1 –ne n2   整数1不等于整数2
  <                   小于,需要双括号,双花括号,单花括号需要转义,如((“$a” < ”$b”)),[[ $a < $b ]],[ $a \< $b ]
                     大于,需要双括号,双花括号,单花括号需要转义
  >=                大于等于,需要双括号,双花括号,单花括号需要转义
  4)判断文件
  File1 –efFile2两个文件具有同样的设备号和i结点号
  File1 –ntFile2文件1比文件2 新
  File1 –otFile2文件1比文件2 旧
  –b File            文件存在并且是块设备文件
  –c File            文件存在并且是字符设备文件
  –d File            文件存在并且是目录
  –e File            文件存在
  –f File             文件存在并且是正规文件
  –g File             文件存在并且是设置了组ID
  –G File             文件存在并且属于有效组ID
  –h File             文件存在并且是一个符号链接(同-L)
  –k File             文件存在并且设置了sticky位
  –b File             文件存在并且是块设备文件
  –L File             文件存在并且是一个符号链接(同-h)
  –o File             文件存在并且属于有效用户ID
  –p File             文件存在并且是一个命名管道
  –r File             文件存在并且可读
  –S File             文件存在并且是一个套接字
  -s file            文件不是空的
  –t FD            文件描述符是在一个终端打开的
  –u File             文件存在并且设置了它的set-user-id位
  –w File             文件存在并且可写
  –x File            文件存在并且可执行
  test的诀窍:
  需有参数:所有的shell变量展开都应该以引号括起来,即使它已变成null。
  字符串比较式很微妙的:特别是字符串值为空,或是开头带有一个减号时,test命令会被混淆。因此有了一种比较难看不过广为使用的方式:在字符串前置字母X。如:if [ “X$answer” = “Xyes” ]。
  test是可以被愚弄的:当我们要检查通过网络加载的文件系统访问时,就有可能将加载选项与文件权限相结合,以欺骗test,使其认为文件是可读取的,但事实是:操作系统根本就不让你访问这个文件。
  test –r a_file && cat a_file#在test –r和执行cat之间的处理期间修改文件属性
  只能做整数数字测试:你不能使用test做任何的浮点数算术运算。所有的数字测试只可处理整数。
unix shell中(),[]和[[]]的区别
  1. 首先,尽管很相似,但是从概念上讲,二者是不同层次的东西。
  &quot;[[&quot;,是关键字,许多shell(如ash bsh)并不支持这种方式。ksh, bash(据说从2.02起引入对[[的支持)等支持。
  &quot;[&quot;是一条命令, 与test等价,大多数shell都支持。在现代的大多数sh实现中,&quot;[&quot;与&quot;test&quot;是内部(builtin)命令,换句话说执行&quot;test&quot;/&quot;[&quot;时不会调用/some/path/to/test这样的外部命令(如果有这样的命令的话)。
  2.[[]]结构比Bash版本的[]更通用。在[[和]]之间的所有的字符都不会被文件扩展或是标记分割,但是会有参数引用和命令替换。
  用` `.``.``.` `测试结构比用[ ... ]更能防止脚本里的许多逻辑错误。比如说,&&,||,操作符能在一个[[]]测试里通过,但在[]结构会发生错误。
  3.(( ))结构扩展并计算一个算术表达式的值。如果表达式值为0,会返回1或假作为退出状态码。一个非零值的表达式返回一个0或真作为退出状态码。这个结构和先前test命令及[]结构的讨论刚好相反。
  4.[ ... ]为shell命令,所以在其中的表达式应是它的命令行参数,所以串比较操作符&quot;>&quot; 与&quot;、>=、&2
  exit 1
  fi
  上面看起来比较难以阅读,使用case就比较清晰了。
  case $1 in
  -f)
  …
  ,,
  -d|--directory)
  …
  ,,
  *)
  echo $1:unknown option >&2
  exit 1
  ,,
  #在”esac”前加,,形式是一个好习惯
  esac
循环
  lfor循环
  for i in list
  do
  command
  done
  for循环里的in列表可选,省略shell循环会遍历整个命令行参数。就好像你已经输入了for i in $@
  for i
  do
  case $i in
  -f)    …
  ,,
  esac
  done
  lwhile与until循环
  while condition                until condition
  do                                                do
  statements                                     statements
  done                                           done
  他们的区别在于对待condition的退出状态。until只要condition是成功退出,while会继续循环。只要condition未成功退出,until则执行循环。
  lbreak与continue
  break是中断并跳出指定的循环个数,继续执行后面的代码。例如如果是2层循环,break 2就完全跳出整个循环。
  continue会跳出当前循环,继续执行后面的代码。

页: [1]
查看完整版本: shell复习摘要(一)