Ksh93 高级特性简介

来源:developerWorks 中国 作者:陈 剑
  
ksh 是 UNIX/Linux 下流行的 shell 语言,ksh93 是 ksh 的增强型版本;相比于 ksh,ksh93 提供了更接近于高级语言的特性,包括 c 风格的 for 循环,关联数组,名字引用,复合变量和更方便的字符串操作,本文讨论了这些高级特性并说明它们的应用。

ksh 是各种 UNIX 下的主要 shell 编程语言,许许多多的 UNIX 开发人员每天都在使用 ksh 做为它们日常的工作工具,当前比较流行的 ksh 版本主要有两个,ksh88 和 ksh93 ;相对于 ksh88,ksh93 提供的特性让 shell 编程人员的效率更加高效,下面我们逐一讨论这些特性。

c 风格的 for 循环

传统的 shell for 循环使用 for i in set 形式:

for i in 1 2 3 4 5 
 do 
 echo $i 
 done

ksh93 提供了对 c 风格 for 循环的支持,如下所示:

for((i=0; i<5; i++)) 
 do 
    echo $i 
 done 


对于在“ (( ”,“ )) ”中出现的 shell 变量,不需要在这些变量前加 $ 符号,比如

这项功能的加入也许是为了适应 c 编程人员众多这个事实,所以受到 c 程序员的广泛欢迎。

count=5 
 for((i=0; i<count; i++)) 
 do 
 echo $i 
 done





关联数组

普通数组使用整数做为下标,关联数组则是使用字符串作为下标。使用关联数组可以很容易的将两方相互联系起来,这两方在关联数组中表示为数组字符串下标和数组值。

要使用关联数组,首先要声明它,下行语句声明 dict 为关联数组。

typeset -A dict

有两种方法可以给 dict 赴初值;这是第一种,

dict[tree]="a lot of leaves" 
 dict[apple]="eclipse fruites"

这是第二种,

dict=( 
 [tree]="a lot of leaves" 
 [apple]="eclipse fruit" 
 )

要遍历 dict,使用如下代码

for i in ${!dict[*]};       # ${!dict[*]} 返回关联数组 dict 的所有下标
 do 
 echo ${dict[$i]};       # $i 是 dict 下标; ${dict[$i]} 取出 dict 的每个元素的值
 done





名字引用

名字引用使函数参数传递,引用和修改更加简单。在没有引入名字引用之前,为了能在函数内部访问实参,一种可选的方法是使用 eval 来实现间接变量引用,ksh93 使用名字引用使得这类代码实现更加直观和易读。下例在函数 foo 中用“ typeset -n larray=$1 ”定义了局部变量 larray,它是 foo 的的第一个参数的名字引用;也可以使用“ nameref larray=$1 ”得到相同的效果。

array=(1 2 3) 
 function foo 
 {typeset -n larray=$1   # larray是形参;typeset i 

 for i in ${larray[*]} 
 do 
    echo $i 
 done 
 # 对形参 larray 做赋值操作,也就改变了实参
 larray[0]=3; larray[1]=2; larray[2]=1; 

 }

运行 foo,将数组 array 作为参数

> foo array                                # array 是实参
 1 
 2 
 3 
 > echo ${array[*]}                           # array 确实被 foo 改变了
 3 2 1





复合变量

复合变量提供了类似于高级语言中结构的功能。

以下 ksh 语句使用复合变量定义了 desk 变量,它有三个域 name,id 和 price 。

desk=( 
 typeset name=yijia 
 integer id=1 
 float   price=340.5 
 )

使用 ${desk.name} 来引用 desk 的 name 域

> echo ${desk.name} 
 yijia

将复合变量和间接变量引用相结合就能用 ksh93 实现教科书上线性链表等标准数据结构。

以下例子给出长度为 2 的一个线性链表,读者可以用类似方法模仿树的实现。

注意,我们称 next 为指针,仅是借用了 c 语言指针的说法,它和 c 中的指针在实现上是不一样的,但是概念类似,即都是属于间接访问这个类型。

#!/bin/ksh 
 # /tmp/link.sh 

 second=(                                    # 复合变量 second,next 指针为空
 data=1 
 next=null 
 ) 
 first=(                                      # 复合变量 first,next 指针为 second 
 data=2 
 next=second 
 ) 
 p=first                                      # 将指针 p 初始化为 first 
 while [[ $p != "null" ]]                     # 如果指针 p 为空,退出循环
 do 
    eval data=\${${p}.data}; echo "data=${data}";        # 取出和打印元素 data 
    eval p=\${${p}.next};    echo "p=$p";                # 将 p 指向下一个元素
 done 

 > /tmp/link.sh                                           # 执行 link.sh 
 data=2 
 p=second 
 data=1 
 p=null





更方便的字符串操作

程序员日常工作中是经常遇到的操作之一就是字符串操作,ksh93 自然不会放过这方面的增强。

表 1 总结了 ksh93 在字符串处理方面的加强,假设 string 等于 abc123abc 。


表 1. 更强的字符串处理
功能 语法 样例
求起始位置为 index 的子串 ${param:offset} > echo ${string:3}
123abc
求起始位置为 index 和长度 num 的子串 ${param:offset:num} > echo ${string:1:3}
bc1
替换第一个出现的 pattern为 repl ${parm/pattern/repl} > echo ${string/abc/def}
def123abc
替换所有出现的 pattern 为 repl ${parm//pattern/repl} > echo ${string//abc/def}
def123def
替换开头的 pattern ${parm/#pattern/repl} > echo ${string/#abc/def}
def123abc
替换结尾的 pattern ${parm/%pattern/repl} > echo ${string/%abc/def}
abc123def

时间:2009-07-16 16:53 来源:developerWorks 中国 作者:陈 剑 原文链接

好文,顶一下
(4)
100%
文章真差,踩一下
(0)
0%
------分隔线----------------------------


把开源带在你的身边-精美linux小纪念品
无觅相关文章插件,快速提升流量