`
scm002
  • 浏览: 317184 次
社区版块
存档分类
最新评论

<<高级Bash脚本编程>> 学习笔记

 
阅读更多

http://blog.csdn.net/gsnumen/article/details/7288204

 

第二部分 基本

3 特殊字符

#

    (1) 注释,从"#"至行尾都是注释
    (2) 模式匹配,如 ${##}
    (3) #!指示脚本解释器

;     命令分隔符,  

;;    case终止符

.
    (1) 等价于source,是bash的内建命令
    (2) 文件和目录的一部分
    (3) 正则匹配中的字符匹配

"    部分引用

'    全引用

        全引用和部分引用的区别:全引用阻止'string'中所有的特殊字符,部分引用阻止'string'中的部分引用,如 $var 变量引用不会被阻止

,    逗号操作符 和C中类似。

\    转义符[反斜线] 作用: 转义

/    文件名路径分隔符

`    命令替换符,`ls -l`, 类似功能的还有: $(ls -l)

:    空命令[冒号],bash内建命令,等价于"NOP",作用与命令"true"相同,还用来做环境变量如"$PATH"的分隔符.

!    取反

*   

    (1) 通配符[星号],用于路径匹配
    (2) 正则表达式的星号
    (3) 算术运算符的 乘号 和 幂

?    测试操作符,正则匹配

$    
    (1) 变量替换
    (2) 正则表达式中的 行尾匹配符

${}    参数替换

$*,$@    位置参数

$?    紧跟上一条命令的退出码

$$    进程ID变量

()    

    (1) 命令组,会常见一个子shell
        
#!/bin/bash  
# parenthesis.sh

var=123
echo "PID is $$"
(var=456;echo"PID is $$";)
echo "var=$var"

exit 0

# 运行结果如下:
#./parenthesis.sh 
#PID is 17665
#PID is 17665
#var=123
(2) 初始化数组
        array=(element1 element2 element3)

{}

    (1) 用于操作文件
        $> touch {a,b,c,d}{1,2,3,4}
        $> ls
        a1 a2 a3 a4 b1 b2 b3 b4 c1 c2 c3 c4 d1 d2 d3 d4
    (2) 代码块
        其实是函数体,如果没有函数名就是"匿名函数"
#!/bin/bash 
# redirect.sh

{
    while read line
    do
        echo $line
    done 
< $
# 文件I/O重定向

{} \;    路径名, 用于 find

    $> find ./ -type f -name "*.sh" -exec echo {} \;

[ ]    

    (1) 条件测试, 条件测试表达式放在[ ]中.
    (2) 数组元素
    (3) 正则表达式中的字符范围.
        $> find ./ -type f -name "[a-h0-9]*.sh" -exec echo {} \;

[[]]    测试, 比[] 更通用,是扩展的shell内建test, 使用[[...]]比[...]能防止脚本中许多逻辑错误.

>   &> >& >> < <> 重定向

< > ASCII comparion

\<...\> 正则表达式中的单词边界

|  管道

    $> ls | tr 'a-z' 'A-Z'

||    逻辑或

&    后台运行命令

&&    逻辑与

-

    (1) 选项前缀
    (2) 用于重定向stdout和stderr
        $> ls | cat - #将ls的结果经过管道给cat,又将cat的结果重定向到stdout
    (3) 先前的工作目录
        $> cd -

=    赋值运算符

+    加法算术操作

%    取模

~    home目录

~+    相当于 $PWD

~-    先前的工作目录

^    正则表达式的行首匹配

空白    分割命令,函数,变量

4 变量和参数的介绍

4.1 变量的名字就是变量保存值的地方,引用变量的值就叫做变量替换
4.2 变量赋值 = 左右不能有空白
4.3 bash变量不区分变量类型.

6 bash脚本的退出码有对应退出状态

    参考: /usr/include/sysexits.h

7 条件判断

7.1 if/then
    (1) bash脚本中,关键字(或者命令)如果作为表达式的开头,并且如果想再同一行再写一个新的表达式的话,那么必须使用分号结束上一个表达式.(P)
    (2) if test condition-true 等价于 if [ condition-true ]
    (3) [[...]] 比 [..]更通用,因为[[...]]能避免一些逻辑上的错误,所以尽量使用[[...]]
    (4) ((...)) 的退出结果与 [...] 相反.
#!/bin/bash 
# if.sh

if [ $1-eq 1 ]
then 
    echo "arg's value: 1";
#else if [ $1 -eq 2 ] #error
#then
# echo "arg's value: 2";
elif [ $1-eq 3 ]
then
    echo "arg's value: 3"
else
    echo "unknow.";
fi

exit 0
#运行结果如下:
#./if.sh 1
#arg's value: 1
#./if.sh 2
#arg's value: 2
#./if.sh 3
#arg's value: 3
#./if.sh 4
#arg's value: 4
 
7.2 文件测试操作符
 
7.3 整数比较运算符, 字符串比较运算符,逻辑或,逻辑与和逻辑非
    (1) 整数比较运算: -eq, -gt, -lt, -ge, -le
    (2) 字符串比较运算符: >, >=, <, <=, !=, -z, -n
    (3) 逻辑运算: -a, -o , !
 

8 操作符

8.1 操作符
    (1) 赋值 =
    (2) 算术操作符
    (3) 位操作符
    (4) 裸机操作符:  && ||
8.2 数字常量
    数字常量默认十进制;数字0开头是八进制;数字0x开头是十六进制;数字符合base#number形式标记的是base进制,图 20#1234, 就是20进制
 

第三部分 进阶

9 变量重游

9.1 内部命令
    (1) $EDITOR    脚本调用的默认编辑器,如vim或者emcase
    (2) $FUNCNAME, $LINENO 当前代码所在的函数名和所在脚本的行号,用于挑事
    (3) $HOME    home目录
    (4) $PATH    可执行文件的搜索路径
    (5) $PS1    主提示符
    (6) $PWD    当前工作目录
    (7) $REPLY    当read命令后不加任何变量时,会将内如保存到 $REPLY
    (8) $SECONDS    脚本到现在为止运行了多少秒
    (9) $TMOUT    脚本运行不得超过的秒数
    (10) $0,$1,$2,... 命令行参数
    (11) $#    命令行参数的个数
    (12) $*, $@ 所有的命令行参数, $@与$*的不同在于, $@是未经任何改变的命令行参数,而$*将命令行参数以空白分割成了一个一个的单词
    (13) caller    调用本函数的函数.
9.2 操作字符串
    啥时候用到啥时候再来温习
 
#!/bin/bash 
# opstring.sh

str=abcABC123ABCabc

# 长度
echo "${str} len: ${#str}"
echo "${str} len: `expr length ${str}`"
echo "${str} len: `expr "$str" : '.*'`"
echo

#匹配字符串开头的子字符串长度
echo "match: `expr match "${str}" 'abc[A-C]*..3'`"
echo "match: `expr "${str}" : 'abc[A-C]*..3'`"
echo

#索引
echo "index: `expr index "${str}" '123'`"
echo

#提取子串
echo "get substring: ${str:3}"
echo "get substring: ${str:3:11}"
echo "get substring: `expr match ${str} '.*\(ABC[1-3]..\).*'`"
echo "get substring: `expr "${str}" : '.*\(ABC[1-3]..\).*'`"
echo

#从头删除子串
echo "delete head substring: ${str#a*A}"
echo "delete head substring: ${str##a*A}"
echo
#从尾删除子串
echo "delete tail substring: ${str%A*c}"
echo "delete tail substring: ${str%%A*c}"
echo

#子串替换
echo "replace substring: ${str/ABC/789}"
echo "replace substring: ${str//ABC/789}"
echo "replace substring: ${str/#abc/789}"
echo "replace substring: ${str/%abc/789}"
 
 
9.3 参数替换
 
#!/bin/bash 
# param.sh

#参数替换
{
# ${param-default} 如果 param 未声明,则使用默认值,否则使用null
#+ ${param:-default} 如果 param 未设置,则使用默认值,否则使用null
    echo "${num-123}, ${num:-123}";
    num=;
    echo "${num-123}, ${num:-123}";
    num=456;
    echo "${num-123}, ${num:-123}";
    echo "${num}"
    echo;
}

{
# ${param=default} 如果 param 未声明,则 param 的值设置为 default,并返回.
#+ ${param:=default} 如果 param 未设置,则 param 的值设置为 defalut,并返回.
    echo "${str="hello kitty"}, ${str:="hello kitty"}";
    str=;
    echo "${str="hello kitty"}, ${str:="hello kitty"}";
    str="How do you do?";
    echo "${str="hello kitty"}, ${sty:="hello kitty"}";
    echo "${str}"
    echo;
}

{
# ${param+val} 如果 param 已声明,则使用 val,否则使用null.
#+ ${param:+val} 如果 param 已设置,则使用 val, 否则使用null.
    unset num ;
    echo "${num+123}, ${num:+123}";
    num=;
    echo "${num+123}, ${num:+123}";
    num=456;
    echo "${num+123}, ${num:+123}";
    echo "${num}";
    echo;
}

{
# ${param?errmsg} 如果 param 已被声明,那么使用它的值,否则打印 errmsg,并 exit
#+ ${param:?errmsg} 如果 param 已被设置,那么使用它的值,否则打印 errmsg,并 exit

    str="Hello World.";
    echo "${str}";
    echo "${str?"str undefault"}, ${str:?"str unset"}";
    srt=;
    echo "${str?"str undefault"}, ${str:?"str unset"}";
    unset str
    echo "${str?"str undefault"}, ${str:?"str unset"}";
    echo;
}

#-, :-
#=, :=
#+, :+
#?, :?
 
9.4 指定bash中的变量类型
    declare 和 typedef 可以用来定义,只读变量、整形变量、数组和函数
9.5 变量间接引用
9.6 $RANDOM Bash内建函数,生成随机数,范围:0~32767
9.7 ((...)) 双圆括号结构,和let功能类似,允许在Bash脚本中使用C语言风格进行变量运算, 返回值与 [..] 刚好相反.
 

10 循环与分支

10.1 循环类型

    (1)  Bash风格的for循环和while循环、以及C风格的for循环和while循环
    (2)  for循环的[list]可以与用命令或者数组等
    (3) while循环的 [condition]有多条时,condition最终退出状态以最后一个条件结果为准。
    for循环:
        for arg in [list]
        do
            command(s)...
        done
    C风格的for循环
        for (())
        do
            command...
         done
    while 循环:
        while [condition]
        do
        done 
10.2 嵌套循环
10.3 循环控制: break、continue
10.4 分支
        case "$var" in
        "$condition1")
            command...
        ;;
        "$condition2")
            command...
        ;;
        ...
        esac
 

11 内部命令和内建命令

    (1) read 读取文件行, 如果read后未跟变量,默认对到 $REPLY 中.
    (2) eval 将表达式中的参数或表达式列表组合起来,执行它们.
    (3) export 声明的变量在所运行的脚本的所有子进程都可用.
    (4) set 声明变量, unset 释放变量.
    (5) readonly 定义只读变量
    (6) getopts 解析命令行参数
    (7) source或.  引用其他脚本代码
    (8) shift 迭代参数列表
    (9) caller 调试用,谁调用了我这个函数.
11.1 作业控制
    (1) jobs 列出后台正在运行的作业.
    (2) wait 在脚本中,用来等待前面执行的后台作业, 直到它们执行完后,wait才会返回,返回作业的退出码.

12 外部过滤器、程序和命令

12.1基本命令

    (1) cat 和tac, 这种tac
    (2) rev    每行内容翻转
        $> echo "1234567890"|rev
        0987654321
    (3)

12.2 复杂命令

     (1) xargs 命令传递参数的一个过滤器
        $> ls | xargs -n6 echo
        $> ls | xargs -i -t cp

12.3 时间/日期

    (1) date 打印和设置系统时间
        $> date -d "2012-02-09 10:02:00" +%s #时间字符串转换为时间戳
        1328752920
        $> date -d @1328752920 #时间戳转换为字符串
        Thu Feb 9 10:02:00 CST 2012
        $> date -d @1328752920 +%Y%m%d" "%H:%M:%S #时间戳转换为字符串,输出指定格式
        20120209 10:02:00
    (2) time 统计程序运行时间
        $> time sleep 10
        real    0m10.003s
        user    0m0.000s
        sys    0m0.002s
        real(real time):实际运行时间,从command执行开始到终止结束的时间
        user(user time):用户CPU时间,command在用户空间运行花费的CPU时间
        sys(system time):系统CPU时间,command在内核态运行花费的CPU时间
        总CPU时间 = 用户CPU时间 + 系统CPU时间;
        实际运行时间大于总CPU时间,说明sleep运行时还有其他程序在运行。
    (3) touch 修改文件的访问时间或修改时间
    (4) cal 日历
        $> cal 03 2012
        $> cal 2012
    (5) sleep, usleep 休眠

12.4 文本处理命令

    (1) cut 剪切命令
        -d指定分隔符;-f指定要剪切出的区域;-s不包含那些不含分隔符的行。
        $> uname -a | cut -d" " -f1,3
        Linux 2.6.18-128.el5
    (2) sort 排序
        -t 指定分隔符;-k按字母倒叙排列第3列。
        $> cat /etc/passwd | sort -t: -k3nr
        nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
        lixianliang:x:506:506::/home/lixianliang:/bin/bash
        ...
    (3) uniq 去重
        $> cat /etc/passwd |cut -d: -f7|sort | uniq -c |sort -nr
         29 /sbin/nologin
          8 /bin/bash
          1 /sbin/shutdown
          1 /sbin/halt
          1 /bin/sync
          1 
    (4) paste 将多文件以列的形式合并成一个文件。
        $> paste /etc/passwd /etc/passwd
        root:x:0:0:root:/root:/bin/bash    root:x:0:0:root:/root:/bin/bash
        bin:x:1:1:bin:/bin:/sbin/nologin    bin:x:1:1:bin:/bin:/sbin/nologin
        ... ...
        $> paste <(ls) <(ls)
    (4) join 合并具有相同标签的两个文件
    (5) head 输出文件头部内容
    (6) tail 输出文件尾部内容
    (7) grep 文本搜索
    (8) sed 行处理
    (9) awk 列处理
    (10) wc 统计文件的单词数量、行数量、字节数量、字符数量,字节最长的行。
    (11) tr 字符转换器
        $> echo "AbcDeFg"|tr 'a-z' 'A-Z'
        ABCDEFG
    (12) fold 折叠文件行
        $> head -3 /etc/passwd|fold -sb24 
        root:x:0:0:root:/root:/b
        in/bash
        bin:x:1:1:bin:/b
        in:/sbin/nologin
        daemon:
        x:2:2:daemon:/sbin:/sbin
        /nologin
    (13) fmt 文件格式器,用于管道
        $> man ls | fmt
    (14) col 过滤掉文件中的反向换行符,用户man page转换为文本
    (15) column 列格式化工具,在合适的地方添加tab键
        $> (printf "PERMISSIONS LINKS OWNER GROUP SIZE MONTH DAY HH:MM PROG-NAME\n";ls -l | sed 1d) | column -t
        PERMISSIONS LINKS OWNER GROUP SIZE MONTH DAY HH:MM PROG-NAME
        -rw-rw-r-- 1 guoshi guoshi 0 Feb 8 17:03 if.sh
        -rw-rw-r-- 1 guoshi guoshi 0 Feb 8 17:03 test.sh
    (16) colrm 列删除过滤器, 删除文件每行的指定列
    (17) pr 格式化打印过滤器
        $> pr -o5 --width=65 /etc/man.config
    (18) iconv, enca 文件字符集转换
    (19) enscript 将文本文件转换成: PostScript, HTML, RTF, ANSI
    (20) 其他文本格式工具:
        groff,tbl,eqn,flex,yacc、

12.5 文件和归档命令

    (1) 压缩和解压缩工具: tar, gzip, gunzip, zip, unzip, bzip2, bunzip2,...
    (2) readlink 读取符号链接文件.

12.6 通讯命令

    hostname, dig, traceroute, ping, whois, finger, sz,rz, ftp, wget, curl, telner, lynx, ssh, scp, mail.

12.7 终端控制命令

    (1) clear 清屏
    (2) script 创建一个会话记录,将用户所有的按键信息保存到文件中。
    (3) 验证文件完整性方法: sum , cksum , md5sum, sha1sum
    (4) dirname 获取目录路径名.

12.8 数学计算命令

    bc

12.9 混杂命令

    (1) seq 产生整数序列,用于for循环
    (2) dd 数据复制
    (3) hexdump
    (4) objdump
    (5) od 将文件转化为8进制或者其他进制显示,主要用于分析二进制文件。

13 系统与管理命令

    知识点: GNU统计工具, binutils工具
    (1) who 显示系统所有登录用户
    (2) w 显示系统所有登录用户,以及他们在做什么,是who的扩展版本.
    (3) last 显示用户最后登录的信息
    (4) 向登录主机上的所有终端的用户发送一条消息
    (5) uname 显示系统信息(OS,内核版本,...), 如 uname -a
    (6) lsof 列出当前所有打开文件的文件信息.
    (7) strace 系统跟踪(System trace),是系统调用和信号的诊断和调试工具.
    (8) ltrace 库跟踪工具(Library trace),跟踪给定命令的调用库相关信息.
    (9) nc 连接和监听TCP和UDP端口.
    (10) free 以表格的形式显示内存和缓存的使用情况.
    (11) du 递归的显示(硬盘)文件的使用情况
    (12) uptime 显示系统时间及当前负载, 显示的信息和w的第一行信息类似.
    (13) df 显示文件系统的使用情况
    (14) stat 显示文件的详细信息,比如:文件大小,inode号,占用文件块数...
    (15) vmstat 显示虚拟内存的统计信息
    (16) netstat 查看当前网络的统计情况和信息.结果从 /proc/net 分析得来
    (17) binutils工具
        readelf, ar, objdump, size,
    (18) 系统日志类
        logger 向系统日志中添加一条消息.
        logrotater 管理系统日志
    (19) 作业控制类
        ps 进程统计
        pgrep, pkill  不习惯用
        pstree 树状显示当前系统中的进程
        top 实时显示进程的CPU,内存等信息.
        nice 修改进程的优先级
        nohup 保证即便是进程的所属用户退出系统,进程还处于运行状态
        kill 发送信号给某个或某些进程
    (20) 启动和进程控制类
        runlevel 查看系统当前运行级别
        halt, shutdown, reboot 关机和重启程序
        service 开启,重启,关闭系统
    (21) 网络类
        ifconfig 网络接口调试和配置.
        iwconfig 无限网络接口调试和配置.
        route 显示内核路由表信息
        chkconfig 管理系统服务的运行级别信息.
        tcpdump 网络包嗅探器, 抓到的包可以用wireshark来解析
        netstat 查看当前网络的统计情况和信息.结果从 /proc/net 分析得来
        ip
        traceroute
    (22) 文件系统类
        mount, umount 挂载,卸载文件系统
        sync, 同步硬盘缓冲区的内容到硬盘
        fdisk 管理存储设备上的分区
        chroot 限定一个程序运行时的根目录
    (23) 其他
        env 打印出环境变量
        ldd 显示可执行文件的动态库的依赖关系
        watch 指定时间内重复运行一次命令,并将结果输出到stdout

14 命令替换

    $(command) 和  `command`,现在$(...)以取代`...`, 并且$(...)可以嵌套.

15 算术扩展

    使用 $(()) 可以使用C语言风格处理数字计算.

16 I/O重定向

    重定向是说: 捕获一个文件,命令,程序,脚本,或脚本中代码块的输出,把这些输出作为输入发送给一个文件,命令,程序或脚本.
    (1) 命令,程序,脚本重定向
        $> cat < ./output.sh  #将stdin重定向到文件
        #!/bin/bash
        echo "$(date +%Y-%m-%d" "%H:%M:%S) into to stdout"
        echo "$(date +%Y-%m-%d" "%H:%M:%S) into to stderr" 1>&2
        $> ./output.sh 1> out #重定向stdout到文件out
        $> ./output.sh 1>> out #重定向stdout并追加到文件out中
        $> ./outout.sh 2> err #重定向stderr到文件err
        $> ./output.sh 2>> err #重定向stderr并追加到文件err中
        $> ./output.sh &> all #将stdout和stderr都重定向到文件
        $> ./output.sh &>> all #将stdout和stderr都重定向并追加到文件
        $> ./output.sh 2>&1 #将标准stderr重定向到stdout
    (2) 代码块重定向
[guoshi@localhost abs_shell]$ cat redirect.sh  
#!/bin/bash
# redirect.sh

while read line
do
    echo "#--> $line"
done < "$1" > "$2"
#将代码块的stdin重定向到"$1"文件, 将代码块的结果重定向到"$2"文件
[guoshi@localhost abs_shell]$ ./redirect.sh ./redirect.sh result
[guoshi@localhost abs_shell]$ cat result 
#--> #!/bin/bash
#--> # redirect.sh
#--> 
#--> while read line
#--> do
#--> echo "#--> $line"
#--> done < "$1" > "$2"
[guoshi@localhost abs_shell]$
    

17 Here Document

18 休息片刻

19 正则表达式

    (1) + GNU版本的sed和awk也可以使用'+', 但必须转移
        $> echo "123aaa4"|sed 's/a\+/A/g'
        123A4
    (2) () 圆括号,括起一组正则表达式
        $> echo -e "123abc4\n123def4"|grep -E '123(abc|def)4'
        123abc4
        123def4

20 子shell

    (...;...;...;) 将开启子shell,子shell中的变量和路径不会影响父shell, 这和父子进程关系类似
    {...;...;...;} 中不会开启子shell

21 受限shell

22 进程替换

    就是把一个命令的结果发送给另一个命令
    >(command)
    <(command)
    例如:
    $> ls
    file1 file2 file3
    $> paste <(ls) <(ls)
    file1    file1
    file2    file2
    file3    file3
    $> cat <(ls) #等价于ls |cat
与"进程替换"类似的是"命令替换": 把一个命令的结果赋值给一个变量,如: filelist=`ls` 或者 filelist=$(ls)

23 函数

    (1) 函数格式
        function func_name()
        {
            ...;
        }
        或者
        func_name()
        {
            ...;
        }
    (2) shell变量间接引用 ${!var}
#!/bin/bash  
# function.sh

#note: shell脚本中变量间接引用时,变量名必须相同.

function param_string()
{
    string="${string/abc/ABC}"
}

function param_int()
{
    : $((num++))
}

function param_test()
{
    local string="abcdef";#local来定义局部变量,作用:只在变量声明的代码中有效
    echo "$FUNCNAME:$LINENO string: [${string}]"
    param_string ${!string};
    echo "$FUNCNAME:$LINENO string: [${string}]"
    local num=5;
    echo "$FUNCNAME:$LINENO num: [${num}]"
    param_int ${!num}
    echo "$FUNCNAME:$LINENO num: [${num}]"
}

param_test
#因为string 和 num 是局部变量 所以这里引用的变量并未定义.
echo "$FUNCNAME:$LINENO string: [${string}]"
echo "$FUNCNAME:$LINENO num: [${num}]"
#./function.sh 
#param_test:19 string: [abcdef]
#param_test:21 string: [ABCdef]
#param_test:23 num: [5]
#param_test:25 num: [6]
#:30 string: []
#:31 num: []
 

24 别名

    bash为了避免输入长命令(包括参数)的麻烦,为这个长命令取个叫断的名字, 就是bash的别名,alias 就想C语言的宏定义.
    如:
        alias ll='ls -l --color=tty'
    shell脚本中默认 alias无效的, 可以使用 shopt -s expand_aliases 已使 alias 生效.
#!/bin/bash 
# mydebug
# Aliases are not expanded when the shell is not interactive, unless the
#+ expand_aliases shell option is set using shopt
shopt -s expand_aliases

case "$1" in
    "debug")
        alias mydebug='echo -n $(caller 0|tr " " ":"):$FUNCNAME:$LINENO:LOG:" "';
        ;;
    *)
        alias mydebug='';
        ;;
esac
 

25 列表结构

    列表结构用来处理一连串连续的命令,有"与列表"和"或列表"
        command1 && command2 && command3 && ...
        command1 || command2 || command3 || ...
    或者 "与列表"和"或列表"的联合使用
        command1 && command2 || command3
    例子:
#!/bin/bash 
# param.sh

if [[ ! -"$1" ]]&& [[ ! -"$2" ]] && [[ ! -z"$3" ]]
then
    :
else
    echo "param invalid.";
    exit 1;
fi

26 数组

 Q1: 如何传递数组
#!/bin/bash
 
function array_common() 
{
# 1 bash数组的元素可以不连续,可以不初始化.
# 2 元素的值可以使任意类型.
# 3 元素引用方法: ${ar[INDEX]}
# 4 给数组成员赋值的方法: ar[INDEX]=... 
# 5 给整个数组赋值的方法: ar=(aaa bbb ccc ddd ...)或者
#+ ar=([x]=aaa [y]=bbb [z]=ccc ...)
    local ar[2]=22;
    ar[8]="Hello World!";
    ar[10]=15;
    for ((i=0; i<15; i++))
    do
        echo "ar2[$i] [${ar[$i]}]"
    done
    echo;


    ar[3]=$((${ar[2]}+ ${ar[10]}));
    for ((i=0; i<15; i++))
    do
        echo "ar2[$i] [${ar[$i]}]"
    done
    echo;

    ar_a=(a b 21 c6 e 9)
    for ((i=0; i<15; i++))
    do
        echo "ar2[$i] [${ar_a[$i]}]"
    done
    echo;

    ar_b=([1]=5 [3]=aa [5]=ll [10]="hhh")
    for ((i=0; i<15; i++))
    do
        echo "ar2[$i] [${ar_b[$i]}]"
    done
    echo;
}

array_common
 

27 /dev/和/proc

28 Zero和Null

  (1) /dev/null: 写入的任何内容都会消失,读不出任何文件.
        
$> cat output.sh 
#!/bin/bash
# common.sh
 
echo "$(date +%Y-%m-%d" "%H:%M:%S) into to stdout"
echo "$(date +%Y-%m-%d" "%H:%M:%S) into to stderr" 1>&2
$> ./output.sh 
2012-02-15 18:55:03 into to stdout
2012-02-15 18:55:03 into to stderr
$> ./output.sh > /dev/null 
2012-02-15 18:55:08 into to stderr
$> ./output.sh 2>/dev/null > /dev/null 
$> ./output.sh 2>/dev/null
2012-02-15 18:55:23 into to stdout
$> ./output.sh &>/dev/null
$> 
 
    (2) /dev/zero: 读出的内容都是非ASCII类型的二进制的0流,写入的内容都会丢失.
        $> dd if=/dev/zero of=1MB bs=1MB count=1

29 调试

    (1) $FUNCNAME, $LINENO, caller

30 选项

    /bin/bash -x script.sh #执行每条命令之前把命令完整的打印出来.

31 陷阱

    (1) =,>,<,>=,<=,!= 这些符号用来进行字符串比较
    (2)-eq, -gt, -lt, -ge, -le, -ne 这些用来比较整数

32 脚本编程风格

    (1) 系统性的退出码: /usr/include/sysexits.h

33 杂项

    (1) 对于测试: [[]] 比 [] 更合适
    (2) 对于算术比较 (()) 更有用
    (3) 将shell脚本转换成二进制可执行文件的方法: "Francisco Rosales的shc"
 
后记:
关键词语: GNU工具集, binutils工具, POSIX字符类
 
 
------------- end -------------
From: GS
-------------------------------
 

第四章. 变量和参数介绍

变量 是脚本编程中的如何进行数据表现的办法. 它们可以在算术计算中作为操作数,在一个字符串表达式中作为符号表达抽象的意义或是其他的其它意义。变量是表示计算机内存中保存一种数据需要占的一个位置或一组的位置的标识

 区别变量和变量的值。如果variable1是一个变量的名字,那么$variable1就是引用这个变量的值――即这个变量它包含的数据
在一个双引号(" ")里的变量引用不会禁止变量替换。所以双引号被称为部分引用,有时也称为"弱引用"而在一个单引号里(' ')的变量替换是被禁止的,变量名只被解释为普通的字面意思。所以单引号被称为"全局引用",有时也被称为强引用.

注意$variable实际上只是${variable}的简单的简写形式。在某些场合使用$variable形式会引起错误,这时你可能需要使用${variable}的形式了

变量赋值

=           赋值操作符(它的左右两边不能有空白符)
不要搞混了=和-eq,-eq是比赋值操作更高级的测试.
变量赋值也可以使用$(...) 机制(它是比斜引号更新的方法). 它实际是命令替换的一种形式.
   1 # 摘自/etc/rc.d/rc.local
   2 R=$(cat /etc/redhat-release)
   3 arch=$(uname -m)

Bash变量是无类型的

不同与许多其他的编程语言,Bash不以"类型"来区分变量。本质上来说,Bash变量是字符串,但是根据环境的不同,Bash允许变量有整数计算和比较。其中的决定因素是变量的值是不是只含有数字.

特殊变量类型

环境变量:这种变量会影响Shell的行为和用户接口

位置参数:命令行传递给脚本的参数是: $0$1$2$3 . . .

$0是脚本的名字,$1是第一个参数,$2是第二个参数,$3是第三个,以此类推。在位置参数$9之后的参数必须用括号括起来,例如:${10}${11}${12}.
特殊变量$*和$@ 表示所有的位置参数。$#表示参数的总个数。
shift命令使位置参数都左移一位。

引用

引用意味着保护在引号中的字符串. 引用在保护被引起字符串中的特殊字符被shell或shell脚本解释或扩展. (如果一个字符能被特殊解释为不同于它字面上表示的意思,那么这个字符是“特殊”的,比如说通配符 -- *.)

某些程序和软件包可以重新解释或扩展引号里的特殊字符。引号一个很重要的作用是保护命令行上的一个参数不被shell解释,而把此参数传递给要执行的程序来处理它。

引用变量

当要引用一个变量的值时,一般推荐使用双引号。用双引号时$仍被当成特殊字符,允许引用一个被双引号引起的变量。

单引号(' ')和双引号类似,但它不允许解释变量引用,因此,在单引号内的字符$的特殊意思无效了。在单引号内,除了字符',每个特殊字符都只是字面的意思。

转义

转义是引用单字符的方法.在单个字符前面的转义符(/)告诉shell不必特殊解释这个字符,只把它当成字面上的意思。

/n                       表示新行
/r                        表示回车
/t                        表示水平的制表符
/v                        表示垂直的制表符
/b                       表示后退符
/a                       表示“警告”(蜂鸣或是闪动)
/0xx                    翻译成ASCII码为八进制0xx所表示的字符
转义符也提供了写一个多行命令的手段。一般地,每个单独的行有一个不同的命令,而在一行末尾的转义符转义新行符,命令序列则由下一行继续。
如果一个脚本行用一个管道线"|"结束行尾,后面可以再跟一个不必一定要的转义符"/"。然而,好的编程习惯最好加上一个转义符“/”。
exit命令一般用于结束一个脚本,就像C语言的exit一样。它也能返回一个值给父进程。
每一个命令都能返回一个退出状态(有时也看做返回状态).一个命令执行成功返回0,一个执行不成功的命令则返回一个非零值,此值通常可以被解释成一个对应的错误值。除了一些例外的情况,一个行为端庄的UNIX命令,程序或是软件包执行成功能返回0的作为退出码。
有一些退出状态码被用于保留(reserved meanings) 的含义,不应该在用户脚本使用

文件测试操作符

如果下面的条件成立返回真...

-e                   文件存在
-a                   文件存在   这个和-e的作用一样. 它是不赞成使用的,所以它的用处不大。
-f                    文件是一个普通文件(不是一个目录或是一个设备文件)
-s                   文件大小不为零
-d                  文件是一个目录
-b                  文件是一个块设备(软盘, 光驱, 等等.)
-c                  文件是一个字符设备(键盘, 调制解调器, 声卡, 等等.)
-p                  文件是一个管道
-h                  文件是一个符号链接
-L                   文件是一个符号链接
-S                  文件是一个socket
-t                  文件(描述符)与一个终端设备相关, 这个测试选项可以用于检查脚本中是否标准输入 ([ -t 0 ])或标准输出([ -t 1 ])是一个终端.
-r                  文件是否可读 (指运行这个测试命令的用户的读权限)
-w                  文件是否可写 (指运行这个测试命令的用户的读权限)
-x                  文件是否可执行 (指运行这个测试命令的用户的读权限)
-g                  文件或目录的设置-组-ID(sgid)标记被设置, 如果一个目录的sgid标志被设置,在这个目录下创建的文件都属于拥有此目录的用户组,而不必是创建文件的用户所属的组。这个特性对在一个工作组里的同享目录很有用处。
-u                  文件的设置-用户-ID(suid)标志被设置, 一个root用户拥有的二进制执行文件如果设置了设置-用户-ID位(suid)标志普通用户可以以root权限运行。[1] 这对需要存取系统硬件的执行程序(比如说pppd和cdrecord)很有用。如果没有设置suid位,则这些二进制执行程序不能由非root的普通用户调用。

 

 	      -rwsr-xr-t    1 root       178236 Oct  2  2000 /usr/sbin/pppd
 	      
被设置了suid标志的文件在权限列中以s标志表示.

 

-k                  粘住位设置

Commonly known as the "sticky bit," the save-text-mode flag is a special type of file permission. If a file has this flag set, that file will be kept in cache memory, for quicker access. [2] If set on a directory, it restricts write permission. Setting the sticky bit adds a t to the permissions on the file or directory listing.

 	      drwxrwxrwt    7 root         1024 May 19 21:26 tmp/
 	      
If a user does not own a directory that has the sticky bit set, but has write permission in that directory, he can only delete files in it that he owns. This keeps users from inadvertently overwriting or deleting each other's files in a publicly accessible directory, such as /tmp.

 

-O                   你是文件拥有者
-G                  你所在组和文件的group-id相同
-N                  文件最后一次读后被修改
f1 -nt f2                  文件f1f2
f1 -ot f2                  文件f1f2
f1 -ef f2                  文件f1f2 是相同文件的硬链接
!                  "非" -- 反转上面所有测试的结果(如果没有给出条件则返回真).

它比较操作符

二元比较操作符比较两个变量或是数值。注意整数和字符串比较的分别。

整数比较

-eq                  等于

if [ "$a" -eq "$b" ]

-ne                  不等于

if [ "$a" -ne "$b" ]

-gt                  大于

if [ "$a" -gt "$b" ]

-ge                  大于等于

if [ "$a" -ge "$b" ]

-lt                  小于

if [ "$a" -lt "$b" ]

-le                  小于等于

if [ "$a" -le "$b" ]

<                  小于(在双括号里使用)

(("$a" < "$b"))

<=                  小于等于 (在双括号里使用)

(("$a" <= "$b"))

>                  大于 (在双括号里使用)

(("$a" > "$b"))

>=

大于等于(在双括号里使用)

(("$a" >= "$b"))

字符串比较

=               等于

if [ "$a" = "$b" ]

==                  等于

if [ "$a" == "$b" ]

它和=是同义词。

Note

==比较操作符在一个双方括号测试和一个单方括号号里意思不同。

   1 [[ $a == z* ]]    # 如果变量$a以字符"z"开始(模式匹配)则为真.
   2 [[ $a == "z*" ]]  # 如果变量$a与z*(字面上的匹配)相等则为真.
   3 
   4 [ $a == z* ]      # 文件扩展和单元分割有效.
   5 [ "$a" == "z*" ]  # 如果变量$a与z*(字面上的匹配)相等则为真.
   6 
   7 # 多谢Stéphane Chazelas

 

!=                  不相等

if [ "$a" != "$b" ]

操作符在[[ ... ]]结构里使用模式匹配.

<                  小于,依照ASCII字符排列顺序

if [[ "$a" < "$b" ]]

if [ "$a" /< "$b" ]

注意"<"字符在[ ] 结构里需要转义

>                  大于,依照ASCII字符排列顺序

if [[ "$a" > "$b" ]]

if [ "$a" /> "$b" ]

注意">"字符在[ ] 结构里需要转义.

参考例子 26-11 中这种比较的一个应用.

-z                  字符串为"null",即是指字符串长度为零。
-n                  字符串不为"null",即长度不为零.
-a                  逻辑与

如果exp1和exp2都为真,则exp1 -a exp2返回真.

-o                  逻辑或

只要exp1和exp2任何一个为真,则exp1 -o exp2 返回真.

赋值
变量赋值

初始化或改变一个变量的值

                 通用的变量赋值操作符,可以用于数值和字符串的赋值
计算操作符
+                  加                 
-                  减
*                  乘
/                  除
**                求幂

 

   1 # Bash在版本2.02引入了"**"求幂操作符.
   2 
   3 let "z=5**3"
   4 echo "z = $z"   # z = 125

 

%                  求模(它返回整数整除一个数后的余数)

 

 bash$ expr 5 % 3
 2
 	      
5/3 = 1 余 2

 

+=                  "加-等(plus-equal)" (把原变量值增加一个常量并重新赋值给变量)

let "var += 5"会使变量var值加了5并把值赋给var.

-=                  "(减-等)minus-equal" (把原变量值减少一个常量并重新赋值给变量)
*=                  "(乘-等)times-equal" (把原变量值乘上一个常量并重新赋值给变量)

let "var *= 4" 使变量var的值乘上4并把值赋给var.

/=                  "(除-等)slash-equal" (把原变量值除以一个常量并重新赋值给变量)
%=                  "(模-等)mod-equal" (把原变量值除以一个常量整除(译者注:即取模)并重新赋余数的值给变量)

计算操作符常常出现在exprlet命令的表达式中.

位操作符. 位操作符很少在脚本中使用。他们主要用于操作和测试从端口或sockets中读到的数据。“位运算”更多地用于编译型的语言,比如说C和C++,它们运行起来快地像飞。

位操作符

<<                  位左移(每移一位相当乘以2)
<<=                  "位左移赋值"

let "var <<= 2" 结果使var的二进制值左移了二位(相当于乘以4)

>>                  位右移(每移一位相当除以2)
>>=                  "位右移赋值"(和<<=相反)
&                  位与
&=                  "位于赋值"
|                  位或
|=                  "位或赋值"
~                  位反
!                  位非
^                  位或
^=                  "位或赋值"
逻辑操作符
&&            逻辑与

 

   1 if [ $condition1 ] && [ $condition2 ]
   2 # 等同于:  if [ $condition1 -a $condition2 ]
   3 # 如果condition1和condition2都为真则返回真...
   4 
   5 if [[ $condition1 && $condition2 ]]    # Also works.
   6 # 注意&&操作不能在[ ... ]结构中使用.

 

Note

依据上下文,&&也可以在与列表(and list)连接命令中。

||            逻辑或
分享到:
评论

相关推荐

    bash高级编程教程

    总的来说,《高级Bash脚本编程指南》是学习和提升Bash脚本编程技能的宝贵资源。无论你是初学者还是经验丰富的开发者,都能从中受益,掌握更高效、更灵活的系统自动化工具。通过本书的学习,你将能够编写出更加高效、...

    shell脚本编程学习笔记汇总

    shell脚本编程学习笔记汇总 本文档总结了 Linux shell 脚本编程的学习笔记,涵盖了 shell 脚本的定义、编写、权限、存放位置、函数、变量、IF 控制语句、命令退出状态等知识点。 一、shell脚本的定义 shell 脚本是...

    Bash_shell学习笔记

    根据给定的"Bash shell学习笔记"文件信息,我们可以从中提炼出多个重要的IT知识点,具体如下: ### 1. 引言 - **Shell的角色**:Shell作为一个命令解释器和编程语言,在用户与UNIX/Linux系统内核之间提供了一个桥梁...

    自学习,Linux命令行与Shell脚本编程笔记!word版本

    这篇“自学习,Linux命令行与Shell脚本编程笔记”旨在帮助初学者掌握这两个核心技能。 首先,Linux命令行是操作系统与用户交互的主要方式之一,通过输入简单的指令,用户可以执行各种任务,如文件管理、系统监控、...

    Linux零基础学习笔记 Shell编程-菜鸟入门(超详细)

    Linux是开源的操作系统,它的命令行界面,尤其是Shell编程...因此,无论你是技术小白还是希望进一步提升,这份“Linux零基础学习笔记 Shell编程-菜鸟入门”都会是你宝贵的资源。祝你在学习的道路上越走越远,不断进步!

    Unix 脚本编程总结与应用实例及其他内部资料

    "Sed学习笔记.htm"涵盖了流编辑器Sed的用法,Sed是Unix系统中用于文本处理的强大工具,可以实现查找、替换、删除等功能,常用于批量处理文件。"UNIX.Shell编程24学时教程.[it270.com].pdf"可能是更全面的教程,包括...

    入门到熟练 高效 Bash Shell 学习笔记材料书籍 BashNotesForProfessionals

    一本特别实在的 Bash 笔记教程,学习效率很高。...如果你想学习 Bash Shell、Bash 脚本编程,看它绝对没错。免费分享!不用积分,更不用付费! 或者从此处直接下载: https://www.aliyundrive.com/s/w36jDXrd7kz

    shell编程学习笔记

    变量: 变量的赋值和引用 在shell编程中变量没有类型,简称弱类型编程语言,不需要声明,在引用这个变量时会创建它(在变量名前加$符号引用变量的值)。在定义变量时,若String中包含空格、制表符、换行符,需用单...

    Advanced Bash-Scripting Guide 英文原版

    《高级Bash脚本指南》英文原版是一本深入探讨Shell脚本艺术的专业书籍,由Mendel Cooper撰写。这本书致力于帮助读者掌握Bash shell编程的高级技巧和实践方法。以下是书中部分内容的详细解释: 在书的前言部分,作者...

    qnote:快速笔记bash脚本

    通过理解其工作原理和功能,我们可以更好地利用它来提高工作效率,同时也可以学习到Bash脚本编程的一些基础知识。在实践中,我们还可以根据自己的需求对qnote进行定制,以满足个性化的笔记管理需求。

    linux运维学习笔记:Shell脚本调试.pdf

    本文档是一份针对Shell脚本调试的学习笔记,详细介绍了几种常见的调试方法和工具,帮助运维人员快速定位并修复脚本中的问题。 首先,需要了解的是Linux与Windows在文本文件行结束标志上的差异。在Linux系统中,文本...

    linux运维学习笔记:Shell脚本书写规范.pdf

    Linux运维学习笔记:Shell脚本书写规范 Shell脚本是Linux系统中一种极为重要的工具,它能够帮助用户执行批量的命令操作,自动化日常运维任务。编写规范、易于理解的Shell脚本不仅有助于提高工作效率,而且方便日后...

    shell script编程学习笔记

    ### Shell Script 编程学习笔记 #### 一、Shell 脚本初窥 ##### 示例: ```bash #!/bin/sh # 第1行:指定脚本解释器(声明使用的shell名称),这里是用/bin/sh做解释器的。“#!”是一个约定的标记 cd ~ # 第2行:...

    Advanced Bash-Scripting Guide 读书笔记

    在阅读《Advanced Bash-Scripting Guide》这本书的过程中,我们能学到许多有关Bash脚本的高级用法和技巧。这本书对于那些想要提升其Bash脚本编写能力的用户来说是一份宝贵的资料。接下来,我将根据给定文件的部分...

    Linux服务器Shell编程学习笔记linux操作系统 电脑资料.docx

    在这个学习笔记中,我们将深入探讨如何编写和理解Shell脚本。 首先,Shell是Linux操作系统中的一个用户界面,它作为用户与操作系统内核交互的接口。常见的Shell类型有bash(Bourne-Again SHell)、sh(Bourne Shell...

    unix shell编程第三版笔记

    通过深入学习"Unix Shell编程第三版笔记",你将能够编写出高效的自动化脚本,提高工作效率,解决日常的系统管理和开发问题。同时,对Unix Shell的熟练掌握也是成为高级系统管理员或全栈开发者的必备技能之一。

    总结搜集的shell脚本学习笔记(完结篇).pdf

    Shell脚本编程涵盖了从基本的条件控制、循环到更高级的功能,如函数定义、字符串处理和数组操作等。掌握这些基础知识对于编写高效的Shell脚本至关重要。 以上就是文档《总结搜集的shell脚本学习笔记(完结篇)》中...

Global site tag (gtag.js) - Google Analytics