设为首页 友情链接
在线留言 发表文章
加入收藏 广告联系

刺猬首页

| 专案技术 | 网络技术 | 图形图象 | 网络编程 | 网页设计 | 操作系统 | 服务器 | 技术白皮书 | 在线实验室 | 刺猬论坛 |
小说专版  | 数据库 | 设计赏析 | 存储频道 | 网络安全 | 私服架设 |  Solaris | 网站评估 | PC维护技巧 | 下载中心 | 博 客 |
专   题: | Linux | java | cisco | 防病毒 | 刀片 | SOA | iscsi | ASP.NET | SQL | Oracle |
您现在的位置: IT公社 IT community >> Linux专题 >> SHELL >> 教程正文 用户登录 新用户注册
专 题 栏 目
最 新 热 门
最 新 推 荐
相 关 文 章
Bash中对变量的操作
一份ksh的专用变量列表
Linux使用基本知识:修改…
  变量替换之 Final 版(初中级进阶必看)         
变量替换之 Final 版(初中级进阶必看)
 

原版:网中人 shell十三问
GNU bash, version 2.05b

把关于用户变量的总结了一下(本来想再发一个,不过那就有灌水之疑,所以就发在下面了),现完整给出,希望对大家有帮助:

[color=blue]1) 赋值“=”和扩充变量值[/color]
在设定变量的时侯,得遵守如下规则:
* 等号左右两边不能使用区隔符号(IFS),也应避免使用 shell 的保留字符(meta charactor)。
* 变量名称不能使用 $ 符号。
* 由字母和下划线组成,并且变量名称的第一个字母不能是数字(number)。
* 变量名称长度不可超过 256 个字母。
* 变量名称及变量值之大小写是敏感的(case sensitive)
例如:NAME=ice_walk        给变量NAME赋值为ice_walk 
在应用变量NAME的时候,在NAME前加"$"即可。
例如:echo  $NAME

[color=darkblue]扩充"(append)变量值:[/color]
除了shell中的meta,其它的[^a-zA-Z0-9_]几乎都可以作单词边界。这些功能有时候会在程序中有意想不到的作用。例如:
$ a=bcd 
$ echo $a.php 得:bcd.php
$ echo $a%b 得:bcd%b
$ echo /$a/bc 得:/bcd/bc
对于shell中的meta字符,则使用backslash。
$ echo $a\*b 得:bcd*b
用户也可以在命令行上同时对多个变量赋值,赋值语句之间用空格分开:
  X=x Y=y (注意变量赋值是从右到左进行的)
  X=$Y Y=y X的值是y 
X=z Y=$Z Y的值是空 (变量未赋值时,shell不报错,而是赋值为空) 

[color=darkblue]内置命令eval:[/color]
在要求多于一次字符串求值的情况下可以使用内置命令 eval。例如,如果变量 X 有值 $y, 并且若 y 有值 pqr 则:eval echo $X
将回显字符串 pqr。 
一般的,eval 命令求值它的实际参数(与所有命令一样)并把这个结果作为给 shell 的输入来对待。读这个输入并执行作为结果的命令。例如:
wg=\'eval who|grep\'
$wg fred
等价于:who|grep fred
在这例子中,需要 eval 的原因是替换之后不解释元字符如 |。

[color=darkblue]局部变量[/color]
在 BASH 程序中如果一个变量被使用了,那么直到该程序的结尾,该变量都一直有效。为了使得某个变量存在于一个局部程序块中,就引入了局部变量的概念。BASH 中,在变量首次被赋初值时加上 local 关键字就可以声明一个局部变量。

[color=darkred]C-shell的用户应该注意:
C-shell中的赋值不同于Bourne和Korn shell。C-shell使用set命令进行赋值:
$set  LOOK = /usr/mydir      (注意在等号两边要加空格,好像不加也可以)
就象文件名的置换一样,变量名的置换也是在调用程序前进行。在变量替换中,变量的值取代了变量名。例如在:$ls  $LOOK/filename  用 /usr/mydir/filename 做参数调用ls。[/color]

[color=blue]2) 变量替换${}[/color]
Shell 之所以强大,其中的一个因素是它可以在命令行中对变量作替换(substitution)处理。在命令行中使用者可以使用 $ 符号加上变量名称(除了在用 = 号定义变量名称之外),将变量值给替换出来,然后再重新组建命令行。
一般情况下,$var 与 ${var} 并没有啥不一样。但是用 ${ } 会比较精确的界定变量名称的范围,比方说:
$ A=B
$ echo $AB
原本是打算先将 $A 的结果替换出来,然后再补一个 B 字母于其后,但在命令行上,真正的结果却是只会提换变量名称为 AB 的值出来。若使用 ${ } 就没问题了。

[color=darkblue]A、掐头去尾[/color]
假设我们定义了一个变量为:file=/dir1/dir2/dir3/my.file.txt
我们可用 ${ } 分别替换获得不同的值:
${file#*/} 从变量file的字符串左边开始删除字符,直到第一个“/”:dir1/dir2/dir3/my.file.txt
${file##*/} 从变量file的字符串左边开始删除字符,直到最后一个“/”:my.file.txt
${file#*.} 从变量file的字符串左边开始删除字符,直到第一个“.”:file.txt
${file##*.} 从变量file的字符串左边开始删除字符,直到最后一个“.”:txt
${file%/*} 从右部开始拿掉字符,直到遇到(从右部数起的)第一个“/” :/dir1/dir2/dir3
${file%%/*} 从右部开始拿掉字符,直到遇到(从右部数起的)最后一个“/”:(空值)
${file%.*} 从右部开始拿掉字符,直到遇到(从右部数起的)第一个“.”:/dir1/dir2/dir3/my.file
${file%%.*} 从右部开始拿掉字符,直到遇到(从右部数起的)最后一个“.”:/dir1/dir2/dir3/my
记忆的方法为:
# 是去掉左边(在键盘上 # 在 $ 之左边)
% 是去掉右边(在键盘上 % 在 $ 之右边)
单一符号是最小匹配﹔两个符号是最大匹配。
同时要注意:在 # 和 % 后可以使用任何shell中的模式匹配。并非仅限于*、.、/。

[color=darkblue]B、字串提取[/color]
${file:0:5} 提取最左边的 5 个字节:/dir1
${file:3} 去掉前面3个字符
${file:5:5} 提取第 5 个字节右边的连续 5 个字节:/dir2

[color=darkblue]C、字符串替换[/color]
${file/dir/path} 将第一个 dir 提换为 path:/path1/dir2/dir3/my.file.txt
${file//dir/path} 将全部 dir 提换为 path:/path1/path2/path3/my.file.txt
不可以使用 regexp , 只能用shell中 * 、? 的文件扩展方式。

[color=darkred]D、通吃变量名
${!prefix*} 代表所有以prefix开始的变量名,各变量名称之间以空格符分隔
$ ab=1 abc=2 abcd=3
$ echo ${!ab*} 输出:ab abc abcd[/color]

[color=darkblue]E、变量赋值(没设定、空值、非空值)[/color]
[color=red]${#myvar} 计算出变量值的长度
${myvar=default}  若 $myvar 没设定,则输出并取值 default。(保留空值及非空值) 
${myvar:=default}  若 $myvar 没设定或为空值,则输出并取值 default。(保留非空值)
${myvar+default} 若 $myvar 设定为空值或非空值,输出但不取值 default,否则返回空(null)。
${myvar:+default} 若 $myvar 设定为非空值,输出但不取值 default,否则返回空(null)。
${myvar-default} 若 $myvar 没设定,输出但不取值 default。(保留空值及非空值)
${myvar:-default} 若 $myvar 没设定或为空值,输出但不取值 default。(保留非空值)
${myvar?default} 若 $myvar 没设定,将 default 输出至 STDERR。(不取值,保留空值及非空值)
${myvar:?default} 若 $myvar 没设定或为空值,将 default 输出至STDERR。(不取值,保留非空值)


(此表请看下面的图)


变量替换的值也可以是` `括起来的命令:$USERDIR={$Mydir:-`pwd`}
${var:?message} 当没有指定message时,shell将显示一条默认的消息,例如:
  $UNAME=
$echo  ${UNAME:?} 结果显示:sh:UNAME:parameter null or not set
速记法:
n = 慈善家(你没有才给你)
n + 商人(你有才给换)
n - 假慈善家(表明上才给)
n ? 牛皮精(只说不做)
n 加“:”后,相当于把“空值”也当作“unset”值处理,对有值的变量则无影响[/color]

[color=darkblue]F、bash 的组数(array)处理[/color]
一般而言,A="a b c def" 这样的变量只是将 $A 替换为一个单一的字符串,但是改为 A=(a b c def) ,则是将 $A 定义为组数。bash 的组数替换方法可参考如下方法:
${A[@]} 或 ${A[*]} 可得到 a b c def (全部组数);
${A[0]} 可得到 a (第一个组数),${A[1]} 则为第二个组数;
${#A[@]} 或 ${#A[*]} 可得到 4 (全部组数数量);
${#A[0]} 可得到 1 (即第一个组数(a)的长度),${A[3]} 可得到 3 (第一个组数(def)的长度);
A[3]=xyz 则是将第 4 个组数重新定义为 xyz。

[color=blue]3) 清除赋值:unset <变量>[/color]
变量一旦经过 unset 取消之后,其结果是将整个变量拿掉,而不仅是取消其变量值。如下两行其实是很不一样的:
$ A=
$ unset A
第一行只是将变量 A 设定为"空值"(null value),但第二行则让变量 A 不在存在:
$ A=
$ echo $A 打印输出为空
$ unset A
$ echo $A 打印输出为空
请务必能识别 null value 与 unset 的本质区别,这在一些进阶的变量处理上是很严格的。与export一样,unset 命令行也同样会作变量替换(这其实就是 shell 的功能之一),因此:
A=B
B=C
unset $A 事实上所取消的变量是 B 而不是 A 。

[color=blue]4) $( )、` `、$(( ))、(( )) [/color]

[color=darkblue]A、$( )与 ` `(反引号) [/color]
都是用来做命令替换用(command substitution)的。所谓的命令替换与前面的变量替换差不多,都是用来重组命令行:完成引号里的命令行,然后将其结果替换出来,再重组命令行。
例如:$ echo last sunday is $(date -d "last sunday" +%Y-%m-%d) ,如此便可得到上一星期天的日期了。
在操作上,用 $( ) 或 ` ` 都无所谓,只是我"个人"比较喜欢用 $( ) ,理由是:
(1) ` ` 很容易与 ' ' ( 单引号)搞混乱。有时在一些奇怪的字形显示中,两种符号是一模一样的(直竖两点)。
(2) 在多层次的复合替换中,` ` 须要额外的跳脱( \` )处理,而 $( ) 则比较直观。
例如:command1 `command2 `command3` `这是错的。
原本的意图是要在 command2 `command3` 先将 command3 提换出来给command 2 处理,然后再将结果传给 command1 `command2 ...` 来处理。然而,真正的结果在命令行中却是分成了 `command2 ` 与 `` 两段。
正确的输入应该是:command1 `command2 \`command3\` `
要不然,换成 $( ) 就没问题了:command1 $(command2 $(command3))
不过,$( ) 并不是没有弊端的, ` ` 基本上可用在全部的 unix shell 中使用,若写成 shell script ,其移植性比较高。而 $( ) 并不见的每一种 shell 都能使用,只能说,若你用 bash2 的话,肯定没问题!
例:通过$()实现对某目录下文件进行操作的功能:
#!/bin/bash
j=$(ls $1)
for k in $j
do
  echo "$k"
  if [ $k = text ]
  then
    cat $k
  else
    echo no text
  fi
done

[color=darkblue]B、$(( ))用来作整数运算[/color]
在 bash 中,$(( )) 的整数运算符号大致有这些:
+ - * / :分别为 "加、减、乘、除"。
% :余数运算
& | ^ !:分别为 "AND、OR、XOR、NOT" 运算。
例:
$ a=5; b=7; c=2
$ echo $(( a+b*c ))      #得19
$ echo $(( (a+b)/c ))    #得6
$ echo $(( (a*b)%c))     #得1
在 $(( )) 中的变量,可用 $ 符号来替换,也可以不用,如:$(( $a + $b * $c)) 也可得到 19 的结果。此外,$(( )) 还可作不同进位(如二进制、八进位、十六进制)作运算呢,只是,输出结果皆为十进制而已:
echo $((16#2a))   结果为 42 (16进位转十进制)
以一个实用的例子来看看吧:
假如当前的 umask 是 022 ,那么新建文件的权限即为:
    $ umask 022
$ echo "obase=8;$(( 8#666 & (8#777 ^ 8#$(umask)) ))" | bc
644

[color=darkblue]C、用 (( ))重定义变量值或作testing[/color]
a=5; ((a++)) 可将 $a 重定义为 6
a=5; ((a--)) 则为 a=4
a=5; b=7; ((a < b)) 会得到 0 (true) 的返回值。
常见的用于 (( )) 的测试符号有如下这些:
<:小于
>:大于
<=:小于或等于
>=:大于或等于
==:等于
!=:不等于
不过,使用 (( )) 作整数测试时,请不要跟 [ ] 的整数测试搞混乱了。



变量替换Linux联盟收集整理

频道声明:本频道的文章除部分特别声明禁止转载的专稿外,可以自由转载.但请务必注明出出处和原始作者 文章版权归本频道与文章作者所有.对于被频道转载文章的个人和网站,我们表示深深的谢意。

原始作者:佚名 录入时间:2007-1-2 2:57:52
信息来源:不详 投稿信箱:itqoo@126.com
教程录入:itqoo    责任编辑:itqoo 
  • 上一个教程:

  • 下一个教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    - 关于我们 - 合作伙伴 - 友情链接 - 广告刊登 - 投稿热线 - 在线留言版权声明联系方式 -
    IT公社版权所有 粤ICP备05127012号
    Copyrigh@2005-2006 itqoo.com.Inc All Rights Reserved  推荐分辨率 1024*768
    联系站长:E-Mail:itqoo@126.com     MSN:urchincc@hotmail.com    QQ:点击这里给我发消息
    特别感谢:亿太网络提供空间支持