pro bash programming学习笔记——第五章

参数和变量


变量的可见性

调用当前shell的shell是看不到当前shell的变量的,而如果调用当前shell的shell将它的变量export到环境中,则可以被当前shell看到。
export的方式为:
var=whatever
export var
这样就把var加入到的环境中,它可以被当前shell的所有子进程看到。
一个变量被export后,除非被unset,否则会一直在环境中。

printf "%s\n" ${RANDOM}{,,,,,} |
  while read num
  do
     [ $num -gt ${biggest:=0} ] && biggest=$num
  done
printf "The largest number is: %d\n" "$biggest"

输出将会是0,问题并不是在while循环,而是因为while循环是整个管道的一部分,而管道是被看成是子shell。
在前一章已经提到过,可以用命令代替来解决这个问题:
while read num
do
   [ $num -gt ${biggest:=0} ] && biggest=$num
done < <(printf "%s\n" ${RANDOM}{,,,,,}) 
printf "The largest number is: %d\n" "$biggest"
这是因为在这种情况下,while循环仍然在当前shell中。

注意:在前一情况下,就算在当前shell中将biggest export到环境中也只能得到0,这个应该跟写时复制有些类似,当子进程对与父进程共有的变量进行改动时,该变量会复制一份到子进程,改动的被会是这个复制版本,父进程中该变量不会有改变。

shell变量

shell有80多个变量,其中有大约一半由shell自动赋值,其他的由操作系统、用户、终端和脚本设定。
前面已经介绍过的一些shell变量有:RAMDOM,PWD,OPTIND,OPTARG 等。
有时候BASH_VERSION(或BASH_VERSINFO)可以用来查看当前运行的shell能否运行该脚本。如:
case $BASH_VERSION in
  [12].*) echo "You need at least bash3.0 to run this script" >&2; exit 2;;
esac

变量命名

传统上来说,环境变量应该用大写字母来命名,本地变量应该用小写字母来命名,但考虑到shell自带有80个变量,如果用大写字母来命名的话很容易造成冲突,所以一般大写字母命名的变量前面最好加一个下划线(因为shell变量都不是以下划线开头的)。

参数扩展

bourne shell

${var:-default}:如果var是unset或为空,则结果为default。
${var-default}:如果var是unset,则结果为default。
相反
${var:+alternate}:如果var不为空,则结果为alternate。
${var+alternate}:如果var是set,则结果为alternate。
以上都不改变var的值。
如:
var=
for n in a b c d e f g
do
   var="${var:+"$var "}$n"
done
sa "$var"
输出将a,b,c,d,e,f,g以空格为分开,但a前面和g后面都没有空格。

${var:=default}与{var:-default}类似,只是会改变var的值。
类似有:
${var=default}

${var:?message}:如果var为空则输出message。
${var?message}:如果var是unset,则输出message。

POSIX shell

${#var}:结果为var的长度。
${var%PATTERN}:去掉var尾部与PATTERN匹配的最短串。(可以用这个获得上层目录的路径)
${var%%PATTERN}:去掉var尾部与PATTERN匹配的最长串。
${var#PATTERN}:去掉var头部与PATTERN匹配的最短串。
${var##PATTERN}:去掉var头部与ATTERN匹配的最长串。(比如说前面几章里提到的一个例子里有scriptname=${0##*/})

bash

${var//PATTERN/STRING}:将var中所有匹配PATTERN的子串换成STRING。
${var/PATTERN/STRING}:只替换第一个匹配的。
如:
passwd=zxQ1.=+-a
printf "%s\n" "${passwd/[[:punct:]]/*}"


输出将会是:
zxQ1*=+-a
([[:punct:]]匹配点)

${var:OFFSET:LENGTH}:结果为从OFFSET 开始长度为LENGTH的子串,OFFSET从0开始,LENGTH可以不指定,此时会输入从OFFSET到末尾的子串。
OFFSET为负数时则从字符串尾开始数。为了与前面提到的:-区分开,这时的负号前面要有空格。
${!var}:间接引用。
如:
x=yes
a=x
sa "${!a}"
则输出为
:yes:
这相当于命令:
eval "sa \$$a"

bash-4.0

${var^PATTERN}:如果第一个字符符合PATTERN,则将其改为大写。如果PATTERN为空,则认为匹配。
${var^^PATTERN}:var中任一字符如果符合PATTERN,则将其改为大写。
${var,PATTERN}
${var,,PATTERN}与前两个类似,只是改为小写。

位置参数

$0为脚本所在的路径。
shift:将参数左移,$2变为$1,$3变为$2等等。$0不变。
shift后可接参数使一次移动几位。
shift "$#"将会移掉所有的位置参数。
于是依次获取各个位置参数可以有以下两种方法:
for param in "$@" ## or just:
do
   : do something with $param
done
while [ $# -gt 0 ] ## or: while [ -n "$*" ]
do
   : do something with $1
   shift
done

数组

bash是支持一维数组的(POSIX shell是不支持的),数组的下标为整数,从4.0开始也可以用字符串作为下标。

要获得数组中的第n项用${array[n]}。
${array[*]}会将array作为一个参数输出。
${array[@]会将array每个元素作为一个参数输出。(类似于$*和$@)

对数组中的第n项赋值则用array[n]=var即可。
${#array[@]}得到的是数组中元素个数。

还可以这样对数组赋值:
province=( Quebec Ontario Manitoba )
用+=对数组添加元素。
province+=( Alberta "British Columbia" "Nova Scotia"  )
注意空格。

如果要用字符串作为数组的下标,则要进行声明:
declare -A array

${array["c"]}得到array中以c为下标的元素。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值