中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > Shell
bash暗黑破坏神(1)
作者:未知 时间:2005-09-13 23:27 出处:Blog.ChinaUnix.net 责编:chinaitpower
              摘要:bash暗黑破坏神(1)
bash中的变量,就象PERL中的变量一样, 是无类型的, 或者话反过来说, PERL学了shell中的变量规则, 是弱类型的.
<<Advanced Bash−Scripting Guide>>一书中有一章专门讲这个, 其实就我的使用经验来说, 这种特性是弊大于利...

#!/bin/bash
# int.or.string.sh: Integer or string?
a=2334 # Integer.
let "a += 1"
echo "a = $a " # a = 2335
echo # Integer, still.
b=$ # Substitute "BB" for "23".
# This transforms $b into a string.
echo "b = $b" # b = BB35
declare .i b # Declaring it an integer doesn't help.
echo "b = $b" # b = BB35
let "b += 1" # BB35 + 1 =
echo "b = $b" # b = 1
echo
c=BB34
echo "c = $c" # c = BB34
d=$ # Substitute "23" for "BB".
# This makes $d an integer.
echo "d = $d" # d = 2334
let "d += 1" # 2334 + 1 =
echo "d = $d" # d = 2335
echo
# What about null variables?
e=""
echo "e = $e" # e =
let "e += 1" # Arithmetic operations allowed on a null variable?
echo "e = $e" # e = 1#!/bin/bash
# int.or.string.sh: Integer or string?
a=2334              # Integer.
let "a += 1
echo "a = $a "      # a = 2335
echo                # Integer, still.
b=$        # Substitute "BB" for "23".
                    # This transforms $b into a string.
echo "b = $b"       # b = BB35
declare .i b        # Declaring it an integer doesn't help.
echo "b = $b"       # b = BB35
let "b += 1"        # BB35 + 1 =
echo "b = $b"       # b = 1
ech
c=BB3
echo "c = $c"       # c = BB34
d=$        # Substitute "23" for "BB".
                    # This makes $d an integer.
echo "d = $d"       # d = 2334
let "d += 1"        # 2334 + 1 =
echo "d = $d"       # d = 2335
ech
                    # What about null variables?
e="
echo "e = $e"       # e =
let "e += 1"        # Arithmetic operations allowed on a null variable?
echo "e = $e"       # e = 1
echo                # Null variable transformed into an integer.
                    # What about undeclared variables?
echo "f = $f"       # f =
let "f += 1"        # Arithmetic operations allowed?
echo "f = $f"       # f = 1
echo                # Undeclared variable transformed into an integer.
                    # Variables in Bash are essentially untyped.
exit

echo # Null variable transformed into an integer.
# What about undeclared variables?
echo "f = $f" # f =
let "f += 1" # Arithmetic operations allowed?
echo "f = $f" # f = 1
echo # Undeclared variable transformed into an integer.
# Variables in Bash are essentially untyped.
exit 0

惨了, 原书的#注释在同一列上对的整整齐齐
COPY到这里就成这样了. 写这种书用这种风格我是欣赏的, 讲究
实际, 用第一手的代码说话, 而且都经过测试. 下面是我今天写一个不足百生的SHELL脚本时碰到的变量方面的问题

declare -i i=0
while [ $i -lt $image_height ]
do
   # 提取文件中的图象数据
   let i = i+1
done

######## 中间经过苦干行, 根据我对循环变量的使用习惯, 用i作变量名.
for i in c m y k
do
    # 引用变量 $i, 企图得到 c m y k
done
但此时的四次循环中每次我却都是取了个0.
为什么, 原因在于i变量一旦被声明为整型变量, 后续对它的赋值和一般的加减运算就有了一个整数取向.
如下:
declare -i i=1
i=asdf
echo $i          #你得到的是0, 而且i=asdf 赋值是成功的, 用$?查看值为0
echo asdf | read i
echo $i          #得到的结果一样. 在不同场合下对i的赋值都是一样
let 'i = i + 1234asdf'
echo $i          #得到1234, 表达式中的1234asdf被当作字串, 与i做加减运算时被转换成数字1234, 这个地方不同的bash版本
                    #表现还不一样, 家里机器上的bash2.05.8(1)-release 会报错说 1234asdf太大了....

下面是使用BASH变量的小暗角:
(1)declare -i var声明一个变量后不要再用这个变量做循环子变量, 除非它要遍历的元素全是整数. work-around: declare +i var, 或 unset var
(2)declare -a 声明的数组变量引用时是这样的:
echo $   #第一个元素
得到数组长度:
echo $ 或 $   但@, *并不可以手工展开
echo $  取到的是第3个元素的值, 0,1,2类似于C语言中逗号表达式的次第求值.
declare -a array=(1 2 3 '4 5' 6)
得到的数组是6个元素, 4和5分别是两个元素,''被提前展开. 要给一个元素赋值为'4 5'这个字符串, 需要单独赋值:
ar[0]='4 5'

无法通过unset数组的的某个元素来把数组在此截断, 虽然这样想起来很直观, 比如原来10个元素的数组, 来个
unset ar[1]
现在长度就剩1了, 不然! 数组中可以有空洞, 即有些元素相当于NULL(NUL, NIL, NV)值.
(3)普通变量也可以象数组变量一样被引用, 而数组变量也可以象普通变量一样被使用, 返回的是数组的第一个元素, 虽然这很不直观
普通变量被当作数组变量使用时, 数组变量的第一个元素的值就是那个普通变量的值
declare -i i=1234
echo $    #就是1234喽
i[1]=asdf        #这里赋值同样会失败, i[1]值为0
所以上面那本书里说BASH的变量是untype的, 我觉得说成弱类型的更合适, 虽然它比有些弱类型更弱.

(4)正则表达式中的. 能不能代表非ASCII的二进制数据?
这是个问题, 但处理二进制数据不是正则表达式的主项. 所以关于文本工具处理二进制数据的讨论极少, 下面是我遇到的问题:
var=$(echo 4100000000000 | xxd -r -ps)
var的值是A, 没有后面的0. 其实不光是00, 换成01也一样会被SHELL处理掉.
echo
4100000000000 | xxd -r -ps | sed 's#\(A\).*##' | xxd -g1
结尾的0不会被处理掉, 也就是说. 不能表示\n之外, 还不能表示00, 但奇怪的是:
echo 4100000000000 | xxd -r -ps | sed 's#\(A\)[^a]*##' | xxd -g1
这样取一个简单的补集却又能把这个字符给消除掉. 我在几乎所有的正则表达式表述中都看到.代表除\n之外的所有(是不是字符?).
但sed 至少有这个很不直观的地方, 我不认为有个官方文档中有意识地定义了这一点.



关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有