Bash编程之数组和字符串处理



目录


笔记日期20180405


数组

声名(创建)数组declare -a ARRAY_NAME

数组元素的赋值ARRAY_NAME=("VAL1" "VAL2" "VAL3"...)

引用数组元素:${ARRAY_NAME[INDEX]}


bash的字符串处理工具

字符串切片${var:offset:number}

基于模式取字串${var#*word}

查找替换变量的值${var/pattern/match}

查找并删除变量的某些字符${var/#pattern}

字符大小写转换${var^^}

判断变量赋值${var:-value}


创建临时文件命令

mktemp

install


练习:写一个脚本(复制命令以及其所依赖的库)






变量:存储单个元素的内存空间

数组:存储多个元素的连续的内存空间

数组引用是从编号0开始,属于数值索引

注意:索引也可以支持使用自定义的格式,而不仅仅是数值格式。

引用数组中的元素: ${ARRAY_NAME[INDEX]}


声名(创建)数组:

declare -a ARRAY_NAME

declare -A ARRAY_NAME 关联数组;



数组元素的赋值:

1. 一次只赋值一个元素

ARRAY_NAME[INDEX]=VALUE

例:weekdays[0]="Sunday"

weekdays[4]="Thursday"

2.一次赋值全部元素:

ARRAY_NAME=("VAL1" "VAL2" "VAL3"...)

可以使用命令替换来赋值如:testa=($(ls /))

然后使用此命令来查看此数组全部值 echo ${testa[*]}

3.只赋值特定元素

ARRAY_NAME=([0]="VAL1" [3]="VAL3" ...)


4.使用交互式赋值给数组

read -a ARRAY

每个元素之间加入空格



引用数组元素:${ARRAY_NAME[INDEX]}

注意:省略[INDEX]表示引用下标为0的元素


引用数组的长度(数组中元素的个数): ${#ARRAY_NAME[*]}, ${#ARRAY_NAME[@]}


示例: 生成10个随机数存入数组,并找出其最小值


#!/bin/bash

#

declare -a rand

declare -i MiNum=0


for i in {1..10}; do

    rand[$[$i-1]]=$RANDOM

    echo ${rand[$[$i-1]]}

    [ $MiNum -eq 0 ] && MiNum=${rand[$[$i-1]]}

    [ ${rand[$[$i-1]]} -lt $MiNum ] && MiNum=${rand[$[$i-1]]}


done

echo "Min: $MiNum"



所有元素 ${ARRAY_NAME[*]} ${ARRAY_NAME[@]}


数组切片 ${ARRAY[@]:offset:number}

offset: 要跳过的元素个数

number: 要取出的元素的个数,取偏移量之后的所有元素: ${ARRAY[@]:offset}


向数组中追加元素 ARRAY[${#ARRAY[*]}]


删除数组中的某元素 unset ARRAY[INDEX]



bash的字符串处理工具

字符串切片:

${var:offset:number}

取出字符串的最右侧几个字符:${var: -lengh}

注意:冒号后必须有一个空白字符


如:chart=Balish

echo ${chart:offset:2}

Ba


echo ${chart: -2}

sh


基于模式取字串

${var#*word} 其中word可以是指定的任意字符

功能:自左向右,查找var变量所存储的字符串中,第一次出现word字符,并从左向右

  删除字符至第一次出现word字符处(注意:word字符也会被删除)


# chart=Bllllish

# echo ${chart#*l}

lllish


${var##*word}

功能:自左向右,查找var变量所存储的字符串中,最后次出现word字符,并从左向右

  删除字符至最后一次出现word字符处(注意:word字符也会被删除)


# chart=Bllllish

# echo ${chart##*l}

ish

${var%word*}

功能:自右向左,查找var变量所存储的字符串中,第一次出现word字符,并从右向左

  删除字符至第一次出现word字符处(注意:word字符也会被删除)


# char="/var/log/message"

# echo "${char%/*}"

/var/log


${var%word*}

功能:自右向左,查找var变量所存储的字符串中,最后一次出现word字符,并从右向左

  删除字符至第一次出现word字符处(注意:word字符也会被删除)


# char="/var/log/messssssssage"

# echo "${char%%s*}"

/var/log/me



查找替换变量的值

可以将变量中被查找到的字符串用其它字符串替换


${var/pattern/match}

功能:查找var变量中第一次被pattern匹配到的字符,并用match来替换其字符


# char="Linuuuuuuuuux Machine"

# echo "${char/u/U}"

LinUuuuuuuuux Machine

${var//pattern/match}

功能:查找var变量中所有被pattern匹配到的字符,并用match来替换其字符


# char="Linnnnnnnnnnx Machinnnnnnne"

# echo "${char//n/N}"

LiNNNNNNNNNNx MachiNNNNNNNe


${var/#pattern/match}

功能:查找var变量中行首为pattern匹配到的字符,并用match来替换其字符


# char="root:admin:123:root"

# echo "${char/#root/ROOT}"

ROOT:admin:123:root


${var/%pattern/match}

功能:查找var变量中行尾为pattern匹配到的字符,并用match来替换其字符


# char="root:admin:123:root"

# echo "${char/%root/ROOT}"

root:admin:123:ROOT


查找并删除变量的某些字符

可以删除变量中被查找到的字符串

这里不再做示例与上边的查找替换非常相似,只是后边不指定替换,就会将查找到的删除

${var/pattern} 自左向右查找变量中第一次被pattern匹配到的字符,并删除

${var//pattern} 自左向右查找变量中所有被pattern匹配到的字符,并删除

${var/#pattern} 查找变量中行首被pattern匹配到的字符,并删除

${var/%pattern} 查找变量中行尾被pattern匹配到的字符,并删除


字符大小写转换

可以将变量中的字符做大小写转换

${var^^} 将变量中所有的小写字符转换为大写

${var,,} 将变量中所有的大写字符转换为小写


# char="root:x:0:0:root:/root:/bin/bash"

# echo ${char^^}

ROOT:X:0:0:ROOT:/ROOT:/BIN/BASH


判断变量赋值

判断变量,如果变量有值做何操作,没有值做何操作


${var:-value} 如果变量有值则显示变量的值,如果没有则显示value字符

${var:=value} 如果变量有值则显示变量的值,如果没有值则会将value赋值给变量var

  并显示value

${var:+value} 与-符号相反,var变量有值则返回value。

${var:?error_info} 如果var为空或未设置,则返回error_info,否则返回var的值


[root@mydomain ~]# unset char

[root@mydomain ~]# echo $char


[root@mydomain ~]# echo ${char:=animal}

animal

[root@mydomain ~]# 



为脚本程序使用配置文件

1.定义文本文件,每行"key=value"

2.在脚本中source此文件即可




创建临时文件命令

mktemp - create a temporary file or directory

mktemp [OPTION]... [TEMPLATE]

-d, --directory

              create a directory, not a file

        -p DIR, --tmpdir[=DIR]

        指明临时文件目录位置


    mktemp /tmp/name_file.XXXX

    此命令创建文件后边的X会随机变换一个字符,这样可以使创建的文件不会冲突

    或者重复导致无法创建文件



install - copy files and set attributes

install [OPTION]... [-T] SOURCE DEST

install [OPTION]... SOURCE... DIRECTORY

install [OPTION]... -t DIRECTORY SOURCE...

install [OPTION]... -d DIRECTORY...


options

-g group

-m mode

-o owner


install命令有make命令所没有的功能就是他可以指定复制的文件或者创建的目录的属组,

权限,属主




练习:写一个脚本(复制命令以及其所依赖的库)

1. 提示用户输入一个可执行的命令名称

2. 获取此命令所依赖到的库文件列表

3. 复制命令至目标目录(例如/mnt/sysroot)下对应的路径下

/bin/bash ==> /mnt/sysroot/bin/bash

/usr/bin/passwd ==> /mnt/sysroot/usr/bin/passwd

4. 复制此命令依赖到的所有库文件至目标目录下的对应路径下

/lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld-linux-x86-64.so.2

5. 每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命令,并重复完成

   上述功能,直到用户输入quit退出脚本












答案:表示用时3小时,真心的慢哈哈,

     如果想复制使用,注意版面,有可能有的是一行内容被拆成两行了

#!/bin/bash

#

#Description: This script can copy the commands that you have gaven,

#and the library which the command depended on.


maindir="/mnt/sysroot"

cmd=notquit


copycmd () {

    cmddir=${cmd%/*}/

    [ -d $maindir$cmddir ] || mkdir -pv $maindir$cmddir

    [ -x $maindir$cmd ] && echo "The {${1##*/}} command has existed in $maindir$cmddir." || cp --preserve $cmd $maindir$cmddir

}


function cplib {

    for I in $(ldd $cmd | grep -o "/.*[[:space:]]"); do

        [ -d $maindir${I%/*} ] || mkdir -pv $maindir${I%/*}

        [ -e $maindir$I ] || cp --preserve $I $maindir$I

    done

}

while [ ! $cmd == "quit" ]; do

  read -p "Input CMD:" cmd

  while [ -z $cmd ]; do

    read -p "Please input something:" cmd

  done

  [ $cmd == "quit" ] && break

  if $(which $cmd &> /dev/null); then

    cmd=$(which $cmd)

    copycmd $cmd

    cplib $cmd

  else

    echo "($cmd) is not a Linux's command"

  fi

done