shellb编程基础第五篇             
本章内容:数组

变量:存储单个元素的内存空间
数组:存储多个元素的连续的内存空间,相当于多个变量的集合。
索引:编号从0开始,属于数值索引
注意:索引可支持使用自定义的格式,而不仅是数值格式,即为关联索引,bash4.0版本之后开始支持。
bash的数组支持稀疏格式(索引不连续)
  数组名[索引]
${数组名[索引]}

定义数组:
声明数组:declare -a NAME           声明索引数组
          declare -A NAME           声明关联数组
数组中元素赋值方式
一次只赋值一个元素:     
一次赋值全部元素         
只赋值特定元素                 
交互式数组值赋值        read -a 数组陈列
===================================================================
一次性元素赋值方式:
[root@xiaomag ~]# declare -a name        声明索引数组名称
[root@xiaomag ~]# name[0]=xiaobo        数组元素
[root@xiaomag ~]# name[1]=laozai          数组元素
[root@xiaomag ~]# echo ${name[*]}         调用全部元素
xiaobo laozai
[root@xiaomag ~]# echo ${name[0]}        调用0的元素
xiaobo
[root@xiaomag ~]# echo ${name[1]}        调用1的元素
laozai
===================================================================
一次赋值给全部元素:
[root@xiaomag ~]# name=("xiaobo" "laozai")     数组名称=元素列表
[root@xiaomag ~]# echo ${name[0]}                    输出打印数组0的参数
xiaobo 
[root@xiaomag ~]# echo ${name[1]}                    输出打印数组1的参数
laozai
[root@xiaomag ~]# echo ${name[*]}                     输出打印全部元素
xiaobo laozai
====================================================================
只给特定元素:
[root@xiaomag ~]# name=([0]="xiaobo" [2]="laozai")   数组名称=特定给元素
[root@xiaomag ~]# echo ${name[0]}            
xiaobo
[root@xiaomag ~]# echo ${name[2]}  
laozai
[root@xiaomag ~]# echo ${name[*]}
xiaobo laozai                     
====================================================================
命令行举例交互式数组赋值:
[root@Compro ~]# read -a name          读取数组 名称
xiaomag xiaobo laozai                            写入对应元素
[root@Compro ~]# echo ${name[0]}     0就是第一个元素
xiaomag
[root@Compro ~]# echo ${name[1]}    1就是第二个元素
xiaobo
[root@Compro ~]# echo ${name[2]}    2就是第三个元素
laozai                                                      这叫做索引数组
======================================================================
[root@xiaomag ~]# name[laozai]=xiaobo   
[root@xiaomag ~]# echo ${name[laozai]}
xiaobo
这种叫做关联数组
=====================================================================
引用数组中的元素  $ {name[0]} 
注意 :引用时只给数组名,表示引用下标为0的元素
数组的长度,(数组中元素的个数)
${#name[*]}   
${#name[@]}  就加上括号表示元素中的个数 ,不加表示第一个元素字符中的个数
=============================================================
练习
[root@Compro ~]# vim shuzusuiji.sh          编辑脚本名称
#!/bin/bash                                                
#   
#uesr:Compro
#数组生成10个随机数保存与数组中,并找出其最大值和最小值
declare -a name                                          声明索引数组 name
declare -i max=0                                         声明整数属性
for i in {0..9};do                                            循环 变量i的值,0-9
 name[$i]=$RANDOM                                数组赋值上条命令的值=随机
 echo ${name[$i]}                                        打印数组的随机值
 [ ${name[$i]} -gt $max ] && max=${name[$i]}    条件判断打印的值是否大于0.  如果大于0的话就执行 max=数组$i的元素
done
echo "Max:$max"                                        输出打印上面的$max的值
===================================================
练习
[root@Compro shuzu]# vim oushuzhihe.sh
#!/bin/bash
#
#user:Compro
#写一个脚本,定义一个数组,数组中的元素是/var/log目录下所有以.log结尾的文件;
要统计其下标为偶数的文件中的行数之和
declare -a files                                           声明索引数组 files
files=( /var/log/*.log )                                  数组元素= 路径
declare -i lines=0                                       声明整数属性

for i in $(seq 0 $[${#files[*]}-1]);do           循环 变量i的值 ,追加数组元素
        if [ $[$i%2] -eq 0 ];then                      分支判断变量值等于0
                let lines+=$(wc -l ${files[$i]} | cut -d' ' -f1 )  计算变量值 抽取以空白符为分隔符的第1列的值
        fi
done
echo "Lines: $lines."                                    输出打印结果
==============================================================
引用数组中的元素
所有元素:${数组[@]},${数组[*]}
数组切片:${数组[@]}:offset:number
          offset   要跳过的元素个数
          number   要取出的元素个数
          取偏移量之后的所有元素  ${数组[@]:offset}
向数组中最加元素:
                 数组名称[${#数组元素[*]}]
删除数组中的某元素:导致稀疏格式
                   unset 数组[索引]
关联数组:
        declare -A 数组名称       必选先声明,在调用
        数组名称=([元素1]='val1' [元素2] 'val2'...)
========================================================================

               bash 的字符串处理工具
字符串切片:
     ${#var}     返回字符串变量var的长度     
     ${var:offset} offset返回字符串的变量var中第offset个字符后(不包括第offset个字符)的字符开始,
                          到最后的部分offset的取值在0到 ${#var}-1 之间(bash4.2后,允许为负值)
     ${var:offset:number}  返回字符串变量var中从第offset个字符 后(不包括第offset个字符)
                                的字符开始,长度为number的部分
     ${var: -数字} 取字符串的最右侧几个字符
                         注意:冒号后面必须有一个空白字符      
[root@xiaomag ~]# var=`echo {a..z}`
[root@xiaomag ~]# v=`echo $var |tr -d " "`
[root@xiaomag ~]# echo $v
abcdefghijklmnopqrstuvwxyz
[root@xiaomag ~]# echo ${#v}
26
[root@xiaomag ~]# echo ${v:3}
defghijklmnopqrstuvwxyz
[root@xiaomag ~]# echo ${v:3:5}
defgh
[root@xiaomag ~]# echo ${v: -3}
xyz
=====================================================================                                                                                            
基于模式取字符串:
                           ${var#*word}    其中word可以是指定的任意字符
                            功能:自左而右,查找var变量所存储的字符串中,第一次出现word,
                                         删除字符串开头至第一次出现word字符之间的所有字符
                           ~]# echo ${v#*m}
                                   nopqrstuvwxyz
                           ${var##*word}   同上,不同的是,删除的是字符串开头至

                                                       最后一次由word指定的字符之间的所有内容
                           ~]# file="/var/log/messages"
                           ~]# echo ${file##*/}
                                 messages     
                           ${var%word*}    其中word可以是指定的任意字符
                            功能:自右而左,查找var变脸所存储的字符串中,第一次出现的word,
                                        删除字符串最后一个字符向左至第一次出现word字符之间的所有字符
                            ~]# file="/var/log/messages"
                            ~]# echo ${file%/*}
                                  /var/log
                           ${var%%word*}   同上,只不过删除字符串最右侧的字符向左至

                                                         最后一次出现word字符之间的所有字符
                            url=aaaa:5556:222
                            ~]# echo ${url##*:} 
                                   222       最右侧的
                            ~]# echo ${url%%:*}
                                  aaaa      最左侧的
[root@Compro ~]# var=hacker:x:1005:1005:hacker,,38763415:/home/hacker:/bin/bash
[root@Compro ~]# echo $var
hacker:x:1005:1005:hacker,,38763415:/home/hacker:/bin/bash
[root@Compro ~]# echo ${var#*x}
:1005:1005:hacker,,38763415:/home/hacker:/bin/bash
==============================================================================
查找替换:
        ${var/pattern/substi} : 查找var所表示的字符串,第一次被pattern所匹配到的字符串,以路径替换之
        ${var//pattern/substi} : 查找var所表示的字符串,所有被pattern所匹配到的字符串,以路径替换之
        ${var/#pattern/substi} : 查找var所表示的字符串,行首被pattern所匹配到的字符串,以路径替换之
        ${var/%pattern/substi} : 查找var所表示的字符串,行尾被pattern所匹配到的字符串,以路径替换之查找并删除:
        ${var/pattern}   查找var所表示的字符串中,删除第一次被pattern所匹配到的字符串
    

        ${var//pattern}  所有 
        ${var/#pattern}  行首
        ${var/%pattern}  行尾
字符大小写转换:
        ${var^^}  把var中的所有小写字母转换为大写
        ${var,,}  把var中的所有大写字母转换为小写       
变量赋值:
        ${var:-value}       如果var为空或未设置,那么返回value;否则,则返回var的值
        ${var:+value}      如果var不空,则返回value
        ${var:=value}      如果var为空或未设置,那么返回value,并将value 赋值给var;f否则,则返回var的值
        ${var:?error_info}   如果var为空或未设置,那么返回error_info;否则,

                                          则返回var的值为脚本程序使用配置文件,实现变量赋值
        定义文本文件,每行定义“name=value”
        在脚本中source此文件即可

高级变量用法-有类型变量:
                                             shell变量一般是无类型的,但是bash shell提供了declare和
                                             typeset两个命令用于指定变量的类型,两个命令是完全等价的
declare [选项] 变量名
               -r    name    将变量设置为只读属性
               -i    name    将变量定义为整型数
               -a   name    将变量定义为数组
               -f    name    显示此脚本前定义过的所有函数名及其内容
               -F  name    仅显示此脚本前定义过的所有函数名
               -x   name    将变量声明为环境变量
               -l    name    将变量转为小写字母                            
==============================================================      
间接变量引用:
                        如果第一个变量的值是第二个变量的名字,
                        从第一个变量引用第二个变量的值就称为间接变量引用

var1=var2
var2=var3
var1的是是var2,而var2又是变量名,var2的值为var3,间接变量引用是指通过var1获得不变量值var3的行为
[root@Compro ~]# echo ${!var1}    第一种间接引用格式
var3
bash shell提供了两种格式实现间接变量引用
[root@Compro ~]# n=name
[root@Compro ~]# name=xiaomag
[root@Compro ~]# n1=${!n}
[root@Compro ~]# echo $n1
xiaomag
[root@Compro ~]# eval n3=\$$v1    第二种间接引用格式
[root@Compro ~]# echo $n3
xiaomag
===============================================================          
eval命令
将会首先扫描命令行进行所有的置换,然后在执行该命令。
改名了适用于那些一次扫描无法实现其功能的变量,该命令对变量进行两次扫描
示例:
[root@Compro ~]# cmd=whoami
[root@Compro ~]# echo $cmd
whoami
[root@Compro ~]# eval $cmd
root     
=================================================================      
创建临时文件
mktemp命令  创建的临时文件可避免冲突
mktemo 选项 格式filename.XXX   X至少要出现三个
               -d  创建临时目录
               -p  Dir   指明临时文件所存放目录位置
[root@Compro ~]# mktemp test.XXX   XXX生成随机字符
test.6Gk       执行结果
[root@Compro ~]# mktemp /tmp/test.XXX
/tmp/test.631
[root@Compro ~]# ll /tmp/test.631
-rw-------. 1 root root 0 8月  23 14:28 /tmp/test.631
================================================================
安装复制文件
install命令:
           install [选项] -t  directory=目录来源 将源文件所有参数复制到指定目录
           install [选项] -T  来源   directory 将目标文件视为普通文件
           install [选项] -d  directory 创建空目录
                    -m mode 默认755
                    -o owner
                    -g group
举例:
[root@Compro ~]# install -m 700 -o hacker -g hacker file1 file2    将file复制到file2 并且带有700的权限
rwx------.  1 hacker hacker      257 8月  23 20:50 file2                      执行结果
[root@Compro ~]# install -m 700 -d /testdir/installdir                       创建空目录 给上700权限
[root@Compro ~]# ll /testdir
总用量 0
drwx------. 2 root root 6 8月  23 20:56 installdir                                  执行结果
=============================================================
bash如何展开命令行执行:
                     1 把命令行分成单个命令词
                     2 展开别名
                     3 展开大括号中的声明 ( {} )
                     4 展开波浪符声明( ~ )
                     5 命令替换$() 和 ``
                     6 再次把命令行分成命令词
                     7 展开文件通配(*、?、[abc]等等)
                     8 准备I/O重定向(< 、>)
                     9 运行命令
防止扩展:
         单引号(')防止所有扩展
         双引号(")也防止所有扩展但是一下情况例外
         $ (美元符号)  变量扩展
         ` (反引号)    命令替换
         \ (反斜线)    禁止单个字符扩展
         ! (叹号)      历史命令替换
         反斜线(\)会使随后的字符按愿意解释

bash的配置文件:按生效范围划分,存在两类
全局配置:
         /etc/profile
         /etc/profile.d/*.sh            
         /etc/bashrc

个人配置:
         ~/.bash_profile
         ~/.bashrc

shell登录两种方式:
交互式登录:
           1 直接通过终端输入帐号密码登录
           2 使用 su - username  切换的用户
执行顺序:/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc -->/etc/bashrc
非交互式登录:
            1 su username
            2 图形界面下打开的终端
            3 执行脚本
执行顺序:~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh             


profile为交互式登录的shell提供配置
全局:/etc/profile     /etc/profile.d/*.sh             
个人:~/.bash_profile
功能:用于定义环境变量 ; 运行命令或脚本
bashrc 为非交互式和交互式登录的shell提供配置
全局:/etc/bashrc
个人:~/.bashrc
功能:定义命令别名和函数 ; 定义本地变量

修改profile和bashrc文件后需要生效方法有两种
    重新启动shell进程
    . 或 source

bash 退出任务
保存在~/.bash_logout文件中(用户)
在退出登录shell时运行
可以用于:
    创建自动备份
    清楚临时文件