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

来源:互联网 发布:linux系统查看本机ip 编辑:程序博客网 时间:2024/06/05 03:07

命令行的解析和扩展


首先看这样一个脚本sa:

pre=:post=:printf "$pre%s$post\n" "$@"

注意其中的$@用双引号引起来了,这样会将脚本运行时的参数一个一行输出。比如说,如果输入:

sa a b "c c"

则输出将会是

:a:

:b:

:c c:

但如果直接写$@而不要双相号,输出将会是:

:a:

:b:

:c:

:c:

这说明,bash在执行每条语句时,会对命令行的参数进行解析,它会将参数以没有引在双引号里的空格为分隔分开,然后再时行扩展,最后将结果作为实参传给该命令。


引号

前面已经说了,bash会跟据空格(包括tab和换行)对参数进行分割。但以下空格不包括在内:被单引号或双引号引起来的、被转义符‘\‘转义了的。这些空格都会被看成是单词的一部分。
比如,输入:
 sa \ this "is a" 'demonstration of' \  quotes\ and\ escapes  (quote前面有两个空格)
输出将会是:
: this:
:is a:
:demonstration of:
: :
:quotes and escapes:

在双引号中有双引号字符时要转义,但单引号中有双引号字符或双引号中有单引号字符时都不需要转义。单引号中不能出现单引号(因为单引号中所有字符都不会被转义)。

两个被引起来的词之前如果没有空格将会被合成一个参数。形式为$'string'字符串中string里可以出现转义的单引号。
如:
echo $'\'line1\'\n\'line2\''
输出为:
'line1'
'line2'

大括号


大括号中的参数以逗号分隔,注意逗号两边不能有空格,否则会将大括号看成是一个普通字符。
如:
sa {one,two,three}
输出为:
:one:
:two:
:three:
大括号中还可以表示一个范围内的序列,如:
sa {1..3}
输出为:
:1:
:2:
:3:
sa pre{d,l}ate
输出为:
:predate:
:prelate:

大括号可以嵌套,如:
sa {{1..3},{a..c}}

bash版本4中,数字可以用0填充,增量可以自己指定,如:
sa {01..14..3}
输出为:
:01:
:04:
:07:
:10:
:13:

字符也有类似的,如{a..e..3}

波浪符

sa ~
将输出用户的home目录
~号后面可以接登录名,表示对应用户的home目录(如果用户不存在,则~将被看成是一个普通字符)。

参数和变量

形参和变量名前加$符表示其取值,为了避免歧义,有时形参名或变量名还要用大括号括起来。如:
first=Janelast=Johnsonsa "$first_$last" "${first}_$last"
输出会是:
:Johnson:
Jane_Johnson
这是因为first_也是一个合法的变量名,它会被解释成空。

算术表达式

形式为$(( expression )),注意空格。
如果表达式没有用双引号引起来,则表达式的结果将会受单词分割的影响。

expression中可以用 **来求幂。

命令代入

形式为` command `或$( command )。执行时它们将会被相应命令的执行结果所代替。
如果命令代入没有被双引号引起来,则结果也会受分词影响。

分词

形参、变量、算术表达式的结果和命令代入的结果如果没有被引起来,都要参加分词。
分词是依据IFS(internal field seperator)来进行的。IFS的默认值为$' \t\n'(注意前面已经讲过,如果单引号前面加$符,则其中的转义符是有效的)。
可以对IFS进行赋值来自定义分隔符。
如果设定的IFS中既有空格,也有其他字符,分词过程中,空格将会直接省去,而另一字符将会划定一个领域。如:
IFS=' :'var="qwerty : uiop : :: er " ## : :: delimits 2 empty fieldssa $var

输出将会是:
:qwerty:
:uiop:
::
::
:er:
而如果IFS中没有空格,则在分词过程中,空格将会被保留。

路径名称

如果在没有被引号引起的参数中出现了*,?,[]则首先会查看当前目录下有没有匹配的文件(*号匹配多个字符,?号匹配一个字符,中括号中的多个字符匹配一个如[a-0]匹配a到o的任意一个字符,[[:lower:]]匹配所有的小写字母)。


进程代入

进程代入将会为一个命令或一个命令列表产生一个临时文件。可以用来代替管道。与管道不同的是,当将一条命令的执行结果以管道的形式传一个循环语句时,循环语句中定义的变量在循环外是不可见的。
如:
 s -l |while read perms links owner group size month day time filedo   totalsize=$(( ${totalsize:=0} + ${size:-0} ))doneecho ${totalsize-unset} ## print "unset" if variable is not set
输出将会是unset。
但如果这样写:
while read perms links owner group size month day time filedo   printf "%10d %s\n" "$size" "$file"   totalsize=$(( ${totalsize:=0} + ${size:-0} ))done < <(ls -l *)echo ${totalsize-unset}
则会输出totalsize的值。


解析选项

运行脚本时有时需要输入一些选项,选项就是那些以连词符号开头的参数,有些选项还需要接一个实参,有些不需要,可以一个连词符号后接多个选项名,但这个选项名中最多只能有一个要实参,且有的话必须排在最后。
用getopts来解析。形式为
getopts OPTSTRING var
OPTSTRING中包含选项字母,如果选项要实参的话字母后面要加一个:号。
当getopts解析完所有的参数或遇到一个‘--‘则会成功返回,余下的参数将会作为实参交给脚本。
有一个例子parseopts:
progname=${0##*/} ## Get the name of the script without its path## Default valuesverbose=0filename=## List of options the program will accept;## those options that take arguments are followed by a colonoptstring=f:v## The loop calls getopts until there are no more options on the command line## Each option is stored in $opt, any option arguments are stored in OPTARGwhile getopts $optstring optdo   case $opt in      f) filename=$OPTARG ;; ## $OPTARG contains the argument to the option      v) verbose=$(( $verbose + 1 )) ;;      *) exit 1 ;;   esacdone## Remove options from the command line## $OPTIND points to the next, unparsed argumentshift "$(( $OPTIND - 1 ))"## Check whether a filename was enteredif [ -n "$filename" ]then    if [ $verbose -gt 0 ]    then        printf "Filename is %s\n" "$filename"    fielse    if [ $verbose -gt 0 ]    then       printf "No filename entered\n" >&2    fi    exit 1fi## Check whether file existsif [ -f "$filename" ]then   if [ $verbose -gt 0 ]   then      printf "Filename %s found\n" "$filename"   fielse   if [ $verbose -gt 0 ]   then      printf "File, %s, does not exist\n" "$filename" >&2   fi   exit 2fi## If the verbose option is selected,## print the number of arguments remaining on the command lineif [ $verbose -gt 0 ]then   printf "Number of arguments is %d\n" "$#"fi
OPTIND是下一个选项的索引

相关命令

head:截取文件的前N行,N缺省为10。
cut:截取文件中的列。


原创粉丝点击