Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > 其他编程语言 > bash暗黑破坏神(1)
【标  题】:bash暗黑破坏神(1)
【关键字】:bash
【来  源】:http://blog.chinaunix.net/article.php?articleId=45840&blogId=8681

bash暗黑破坏神(1)

Your Ad Here 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 至少有这个很不直观的地方, 我不认为有个官方文档中有意识地定义了这一点.



计算网络广播地址的shell:【上一篇】
bash暗黑破坏神(2):【下一篇】
【相关文章】
  • 安全撤退的一句话bash 脚本
  • bash Shell中函數的應用小結
  • bash之初
  • bash Bash 实例
  • BASH 中的字符串处理
  • 分析tuxedo的service时间日志的bash脚本
  • Bash 实例
  • bash命令的优先级
  • aix上安装bash
  • Bash 实例:探讨 ebuild 系统
  • 【随机文章】
  • Alsa-sound-mini-HOWTO(二)
  • 梧桐兄策划的EasyVR虚拟现实技术论坛开通了
  • 通过sql*plus输出excel、html格式文件
  • 第十三节 对象串行化
  • DataGrid --> DataGridView in Whidbey
  • Apache HTTP 服务器配置
  • 关于serverSocket和clientSocket文件传输
  • ASP #include
  • 技巧和诀窍:简单的ASP.NET 2.0 SQL提供器的源码和文档发布了
  • 常微分方程
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 bbb软讯网络 All Rigths Reserved.