• RSS订阅
  • 交换链接
  • 首页

Jeffrey’s Blog

Web&P2P系统架构及优化


shell程序中,$(( )) 与 $( ) 还有${ } 差在哪? [zz]

August 23rd, 2007

转自<<网中人的SHELL十三问 >>第8问第8问,最新重看了一遍,感觉又看到了新的东西^_^

 

以下为转贴内容:

 

$(( )) 与 $( ) 还有${ } 差在哪?

在 bash shell 中,$( ) 与 ` ` (反引号) 都是用来做命令替换用(command substitution)的。
所谓的命令替换与我们第五章学过的变量替换差不多,都是用来重组命令行:
* 完成引号里的命令行,然后将其结果替换出来,再重组命令行。
例如:
[code]$ echo the last sunday is $(date -d "last sunday" +%Y-%m-%d)[/code]
如此便可方便得到上一星期天的日期了… ^_^

在操作上,用 $( ) 或 ` ` 都无所谓,只是我"个人"比较喜欢用 $( ) ,理由是:

1,  ` ` 很容易与 ' ' ( 单引号)搞混乱,尤其对初学者来说。
有时在一些奇怪的字形显示中,两种符号是一模一样的(直竖两点)。
当然了,有经验的朋友还是一眼就能分辩两者。只是,若能更好的避免混乱,又何乐不为呢? ^_^

2, 在多层次的复合替换中,` ` 须要额外的跳脱( \` )处理,而 $( ) 则比较直观。例如:
这是错的:
[code]command1 `command2 `command3` `[/code]
原本的意图是要在 command2 `command3` 先将 command3 提换出来给 command 2 处理,
然后再将结果传给 command1 `command2 …` 来处理。
然而,真正的结果在命令行中却是分成了 `command2 ` 与 “ 两段。
正确的输入应该如下:
[code]command1 `command2 \`command3\` `[/code]

要不然,换成 $( ) 就没问题了:
[code]command1 $(command2 $(command3))[/code]
只要你喜欢,做多少层的替换都没问题啦~~~  ^_^

不过,$( ) 并不是没有毙端的…
首先,` ` 基本上可用在全部的 unix shell 中使用,若写成 shell script ,其移植性比较高。
而 $( ) 并不见的每一种 shell 都能使用,我只能跟你说,若你用 bash2 的话,肯定没问题…  ^_^

接下来,再让我们看 ${ } 吧… 它其实就是用来作变量替换用的啦。
一般情况下,$var 与 ${var} 并没有啥不一样。
但是用 ${ } 会比较精确的界定变量名称的范围,比方说:
[code]$ A=B
$ echo $AB

[/code]
原本是打算先将 $A 的结果替换出来,然后再补一个 B 字母于其后,
但在命令行上,真正的结果却是只会提换变量名称为 AB 的值出来…
若使用 ${ } 就没问题了:
[code]$ echo ${A}B
BB[/code]

不过,假如你只看到 ${ } 只能用来界定变量名称的话,那你就实在太小看 bash 了﹗
有兴趣的话,你可先参考一下 cu 本版的精华文章:
http://www.chinaunix.net/forum/viewtopic.php?t=201843

为了完整起见,我这里再用一些例子加以说明 ${ } 的一些特异功能:
假设我们定义了一个变量为:
file=/dir1/dir2/dir3/my.file.txt
我们可以用 ${ } 分别替换获得不同的值:
${file#*/}
:拿掉第一条 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}
:拿掉最后一条 / 及其左边的字符串:my.file.txt
${file#*.}
:拿掉第一个 .  及其左边的字符串:file.txt
${file##*.}
:拿掉最后一个 .  及其左边的字符串:txt
${file%/*}
:拿掉最后条 / 及其右边的字符串:/dir1/dir2/dir3
${file%%/*}
:拿掉第一条 / 及其右边的字符串:(空值)
${file%.*}
:拿掉最后一个 .  及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}
:拿掉第一个 .  及其右边的字符串:/dir1/dir2/dir3/my
记忆的方法为:
[list]#
是去掉左边(在鉴盘上 # 在 $ 之左边)
%
是去掉右边(在鉴盘上 % 在 $ 之右边)
单一符号是最小匹配﹔两个符号是最大匹配。[/list]
${file:0:5}
:提取最左边的 5 个字节:/dir1
${file:5:5}
:提取第 5 个字节右边的连续 5 个字节:/dir2

我们也可以对变量值里的字符串作替换:
${file/dir/path}
:将第一个 dir 提换为 path:/path1/dir2/dir3/my.file.txt
${file//dir/path}
:将全部 dir 提换为 path:/path1/path2/path3/my.file.txt

利用 ${ } 还可针对不同的变量状态赋值(没设定、空值、非空值):
${file-my.file.txt}
:假如 $file 没有设定,则使用 my.file.txt 作传回值。(空值及非空值时不作处理)
${file:-my.file.txt}
:假如 $file 没有设定或为空值,则使用 my.file.txt 作传回值。 (非空值时不作处理)
${file+my.file.txt}
:假如 $file 设为空值或非空值,均使用 my.file.txt 作传回值。(没设定时不作处理)
${file:+my.file.txt}
:若 $file 为非空值,则使用 my.file.txt 作传回值。 (没设定及空值时不作处理)
${file=my.file.txt}
:若 $file 没设定,则使用 my.file.txt 作传回值,同时将 $file 赋值为 my.file.txt 。 (空值及非空值时不作处理)
${file:=my.file.txt}
:若 $file 没设定或为空值,则使用 my.file.txt 作传回值,同时将 $file 赋值为 my.file.txt 。 (非空值时不作处理)
${file?my.file.txt}
:若 $file 没设定,则将 my.file.txt 输出至 STDERR。 (空值及非空值时不作处理)
${file:?my.file.txt}
:若 $file 没设定或为空值,则将 my.file.txt 输出至 STDERR。 (非空值时不作处理)

tips:
以上的理解在于, 你一定要分清楚 unset 与 null 及 non-null 这三种赋值状态.
一般而言, : 与 null 有关, 若不带 : 的话, null 不受影响, 若带 : 则连 null 也受影响.

还有哦,${#var} 可计算出变量值的长度:
${#file}
可得到 27 ,因为 /dir1/dir2/dir3/my.file.txt 刚好是 27 个字节…

接下来,再为大家介稍一下 bash 的组数(array)处理方法。
一般而言,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
则是将第四个组数重新定义为 xyz …

诸如此类的….
能够善用 bash 的 $( ) 与 ${ } 可大大提高及简化 shell 在变量上的处理能力哦~~~  ^_^

好了,最后为大家介绍 $(( )) 的用途吧:它是用来作整数运算的。
在 bash 中,$(( )) 的整数运算符号大致有这些:
+ - * / :分别为 "加、减、乘、除"。
% :余数运算
& | ^ !:分别为 "AND、OR、XOR、NOT" 运算。

例:
[code]$ a=5; b=7; c=2
$ echo $(( a+b*c ))
19
$ echo $(( (a+b)/c ))
6
$ echo $(( (a*b)%c))
1[/code]

在 $(( )) 中的变量名称,可于其前面加 $ 符号来替换,也可以不用,如:
$(( $a + $b * $c))
也可得到 19 的结果

此外,$(( )) 还可作不同进位(如二进制、八进位、十六进制)作运算呢,只是,输出结果皆为十进制而已:
echo $((16#2a))
结果为 42 (16进位转十进制)
以一个实用的例子来看看吧:
假如当前的  umask 是 022 ,那么新建文件的权限即为:
[code]$ umask 022
$ echo "obase=8;$(( 8#666 & (8#777 ^ 8#$(umask)) ))" | bc
644[/code]

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

Last modified at: Thursday, August 23rd, 2007 11:32:28 am
Trackback URL: http://blog.zhangjianfeng.com/article/618/trackback

给本文打分: 1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...
Tags: shell, 十三问, 网中人
2007/08/23 | 阅读全文 | 系统管理 | Email This Post | Print This Post | 1,306 views |
收藏到网摘: Del.icio.us Google书签 Digg Live Bookmark Technorati Furl Yahoo书签 Facebook 百度搜藏 新浪ViVi 365Key网摘 天极网摘 和讯网摘 博拉网 POCO网摘 添加到饭否 QQ书签 Digbuzz我挖网

Related Post

  • Tuesday, March 11th, 2008 -- Shell中的grep、awk和sed的常用命令和语法
  • Thursday, August 3rd, 2006 -- shell笔记

0 Responses to “shell程序中,$(( )) 与 $( ) 还有${ } 差在哪? [zz]”


  1. No Comments

Leave a Reply

  • :em04:
  • :em18:
  • :em17:
  • :em10:
  • :em01:
  • :em05:
  • :em15:
  • :em07:
  • :em03:
  • :em13:
  • :em09:
  • :em12:
  • :em11:
  • :em06:
  • :em16:
  • :em14:
  • :em02:
  • :em08:

« raid5盘阵,做lvm笔记
解密Windows Vista各版本的区别 »

    最新文章

    • Subversion的用户自助修改口令实现(linux测试通过)
    • SLES10-SP1+Apache-2.0.63+SVN-1.4.6安装配置笔记
    • [音乐欣赏]A place nearby
    • 不错的firefox插件---鼠标手势mouse gestures
    • 一些相克食品
    • oracle一次数据迁移笔记
    • 不错的vi-vim键盘图(中英文双版)
    • xen安装及配置笔记
    • Multiple network cards and bridges in Xen[zz]
    • 从LiveJournal后台发展看大规模网站性能优化方法[zz]

    评分最高文章

      • 今天下载的一个CHM文件,打开时右边的内容看不到,提示“该页无法显示”。
      • linux日志服务器配置笔记
      • Legato networker学习笔记(杂)
      • linux tips 技巧笔记
      • [BT下载]2006韩剧-葡萄园的那小伙儿
      • 我家的金吉拉
      • 卡巴斯基病毒库离线更新方法
      • 忽悠姐妹花主题曲下载
      • 轻轻松松把 Apache 配置安全
      • 北京IDC机房介绍

    随机文章:

    • 开源软件名的读音
    • 查询域名对应的MX记录方法
    • iostat 输出解析[zz]
    • 坐公交车出门的朋友小心新骗局!
    • [迷信一下]眼跳测吉凶
    • oracle一次数据迁移笔记
    • 肉体和金钱,怎么选择?美国一著名心理测试
    • 来看看北京“天上人间“去得起吗[zz]
    • 身份证里的"X"原来是这个意思
    • GRUB安装,配置及使用汇总

    最新评论

    • very good :em02: ,I like very much !!...
    • :em03: :em13: :em15: :em07...
    • 北京电信通有四个机房1惠普机房 2中...
    • :em04: :em18: :em17...
    • 结婚的好日子啊8月10...
    • c2950-1-1(config)# snmp-server trap-source FastEt...
    • :em16: :em16: :em16: :em16: :em16: :em16: :...
    • :em01: :em07: :em04: :em17: :em10: :em18: :...
    • 我是天称座 :em14: :em15: :em03: :em02: :...
    • [...] 前面一段:1.3.6.1.4.1. 可以查看这...


    邮件订阅  
  • Categories

    • 个人日志 (15)
    • 休闲娱乐 (79)
    • 应用服务 (86)
    • 影音娱乐 (10)
    • 电脑网络 (78)
    • 站点日志 (19)
    • 系统管理 (242)
    • 英语学习 (15)
    • 衣食住行 (41)
    • 资料共享 (28)
  • 工具网址

    • 天气预报
    • 常用电话
    • 疾病查询
    • 在线翻译
    • Alexa排名查询
    • IP信息查询
    • 邮箱图标生成
    • 我的Firefox插件
  • 友情链接

    • linuxの飘扬
    • winter的平凡生活
    • 伤感星星的天空
    • 回忆未来[张宴]
    • 存储部落
    • 扶凯Blog
    • 沐宇春风
    • 爱MySQL中文网
    • 狗.车.志
    • 非礼勿视
  • Tags

    • 下载 优化 使用 免费 北京 升级 学习 学习笔记 安装 工具 技巧 日志 最新 服务器 笔记 英语学习 菜谱 视频 解决 调优 软件 运程 配置 配置文件 食物 2007 apache blog dreamhost freebsd Legato linux mysql networker oracle php RAID5 RedHat sendmail shell squid suse Ubuntu windows wordpress

Jeffrey's Blog is powered by WordPress 2.3.1 and Unnamed 1.22
Entries (RSS) and Comments (RSS) Admin 京ICP备06038449号

Podcast Powered by podPress (v8.8)