1 字符串处理

1.1 字符串切片

1.1.1 基于偏移量取字符串

  1. #返回字符串变量var的字符的个数长度,一个汉字算一个字符
  2. ${#var}
  3. #返回字符串变量var中从第offset个字符串(不包括第offset个字符)的字符开始,到最后的部分,offset的取值再0到${#var}-1之间(base4.2后,允许为负值)
  4. ${var:offset}
  5. #返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,长度为number的部分
  6. ${var:offset:number}
  7. #取字符串的最右侧几个字符,注意:冒号后必须有一空白字符
  8. ${var: -length}
  9. #从最左侧跳过offset字符,一直向右取到距离最右侧length个字符之前的内容,即 : 掐头去尾
  10. ${var:offset:-length}
  11. #先从最右侧向左取到length个字符开始,再向右侧取到举例最右侧offset个字符之间的内容,注意:-length前空格,并且length必须大于offset
  12. ${var: -length:-offset}

范例:

  1. ~ echo {a..z}|tr -d " "
  2. abcdefghijklmnopqrstuvwxyz
  3. ~ str=$(echo {a..z}|tr -d " ")
  4. ~ echo ${str}
  5. abcdefghijklmnopqrstuvwxyz
  6. ~ echo ${#str}
  7. 26
  8. ~ name="青云"
  9. ~ echo ${name}
  10. 青云
  11. ~ echo ${#name}
  12. 2
  13. ~ echo ${str:3}
  14. ~ echo ${str:3:5}
  15. ~ echo ${str: -3}
  16. ~ echo ${str:3:-3}
  17. ~ echo ${str: -6:-2}
  18. ###
  19. ~ str="abcdef我你他"
  20. ~ echo ${#str}
  21. 9
  22. ~ echo ${str:2}
  23. cdef我你他
  24. ~ echo ${str:2:3}
  25. cde
  26. ~ echo ${str:-3}
  27. abcdef我你他
  28. ~ echo ${str: -3}
  29. 我你他
  30. ~ echo ${str:2:-3}
  31. cdef
  32. #无用的写法
  33. ~ echo ${str:-2:-3}
  34. abcdef我你他
  35. ~ echo ${str: -2:-3}
  36. bash: -3: substring expression < 0
  37. #正确取字符串
  38. ~ echo ${str: -3:-2}
  39. ~ echo ${str:-3:-2}
  40. abcdef我你他
  41. ~ echo ${str: -5:-2}
  42. ef

1.1.2 基于模式取子串

其中word可以是指定的任意字符,自左而右,查找var变量所存储的字符串中,第一次出现的word,删除字符串开头至第一次出现 word 字符串(含)之间的所有字符,即懒惰模式,以第一个word为界删左留右

${var#*word}

同上,贪婪模式,不同的是,删除的是字符串开头至最后一次由 word 指定的字符之间的所有内容,即贪婪模式,以最后一个 word 为界删左留右

${var##*word}

范例:

  1. ~ url=http://www.kubesphere.com/index.html
  2. ~ echo ${url#*/}
  3. /www.kubesphere.com/index.html
  4. ~ echo ${url#*//}
  5. www.kubesphere.com/index.html
  6. ~ echo ${url##*/}
  7. index.html
  8. ~ file="var/log/message"
  9. ~ echo ${file#*/}
  10. log/message
  11. ~ echo ${file##*/}
  12. message

其中word可以是指定的任意字符,自右而左,查找var变量所存储的字符串中,第一次出现的word ,删除字符串开头至第一次出现 word 字符串(含)之间的所有字符,即懒惰模式,以第一个word为界删右留左

${var%word*}

同上,贪婪模式,不同的是,删除的是字符串开头至最后一次由 word 指定的字符之间的所有内容,即贪婪模式,以最后一个 word 为界删右留左

${var%%word*}

范例:

~ file="var/log/message"
~ echo ${file%/*}
var/log
~ echo ${file%%/*}
var

范例:

~ url=http://www.kubesphere.com:8080/index.html
~ echo ${url%:*}
http://www.kubesphere.com
~ echo ${url%%:*}
http

1.2 查找替换

查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substr替换之。(懒惰模式)

${var/pattern/substr}

查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替换之。(贪婪模式)

${var//pattern/substr}

查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substr替换之

${var/#pattern/substr}

查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替换之

${var/%pattern/substr}

范例:查找替换

~ getent passwd root
root:x:0:0:root:/root:/bin/zsh
~ line=$(getent passwd root)
~ echo $line
root:x:0:0:root:/root:/bin/zsh

~ echo ${line/root/rooter}
rooter:x:0:0:root:/root:/bin/zsh
~ echo ${line//root/rooter}
rooter:x:0:0:rooter:/rooter:/bin/zsh
~ echo ${line/#root/rooter}
rooter:x:0:0:root:/root:/bin/zsh
~ echo ${line/%zsh/rooter}
root:x:0:0:root:/root:/bin/rooter

1.3 查找并删除

删除var表示的字符串中第一次被pattern匹配到的字符串

${var/pattern}

删除var表示的字符串中所有被pattern匹配到的字符串

${var//pattern}

删除var表示的字符串中所有以pattern为行首匹配到的字符串

${var/#pattern}

删除var所表示的字符串中所有以pattern为行尾所匹配到的字符串

${var/%pattern}

范例:查找并删除

~ getent passwd root
root:x:0:0:root:/root:/bin/zsh
~ line=$(getent passwd root)
~ echo $line
root:x:0:0:root:/root:/bin/zsh

~ echo ${line/root}
:x:0:0:root:/root:/bin/zsh
~ echo ${line//root}
:x:0:0::/:/bin/zsh
~ echo ${line/#root}
:x:0:0:root:/root:/bin/zsh
~ echo ${line/%zsh}
root:x:0:0:root:/root:/bin/

1.4 字符大小写转换

把var中的所有小写字母转换为大写

${var^^}

把var中的所有大写字母转换为小写

${var,,}

范例:字符大小写转换

~ line=$(getent password root)
~ echo $line
root:x:0:0:root:/root:/bin/zsh
#字符转换为大写
~ echo ${line^^}
ROOT:X:0:0:ROOT:/ROOT:/BIN/ZSH

~ line2=$(echo ${line^^})
~ echo ${line2}
ROOT:X:0:0:ROOT:/ROOT:/BIN/ZSH
#字符转换为小写
~ echo ${line2,,}
root:x:0:0:root:/root:/bin/zsh

~ url=http://www.kubesphere.com:8080/index.html
~ echo ${url}
http://www.kubesphere.com:8080/index.html
~ url=$(echo ${url^^})
~ echo ${url}
HTTP://WWW.KUBESPHERE.COM:8080/INDEX.HTML

~ url=$(echo ${url,,})
~ echo ${url}
http://www.kubesphere.com:8080/index.html

2 高级变量

2.1 高级变量赋值

变量配置方式 str 没有配置 str 为空字符串 str 已配置非为空字符串
var=${str-expr} var=expr var= var=$str
var=${str:-expr} var=expr var=expr var=$str
var=${str+expr} var= var=expr var=expr
var=${str:+expr} var= var= var=expr
var=${str=expr} str=expr
var=expr
str 不变
var=
str 不变
var=$str
var=${str:=expr} str=expr
var=expr
str=expr
var=expr
str 不变
var=$str
var=${str?expr} expr输出至stderr var= var=$str
var=${str:?expr} expr输出至stderr expr输出至stderr var=$str

范例:高级变量赋值

~ unset str;var=${str-kubesphere};echo ${var}
kubesphere
~ str='';var=${str-kubesphere};echo ${var}

~ str="wang";var=${str-kubesphere};echo ${var}
wang

~ title=ceo;name=${title-kubernets};echo ${name}
ceo
~ title='';name=${title-kubernets};echo ${name}

~ unset title;name=${title-kubernets};echo ${name}
kubernets
~ unset str;var=${str:-kubesphere};echo ${var}
kubesphere
~ str='';var=${str:-kubesphere};echo ${var}
kubesphere
~ str="wang";var=${str-kubesphere};echo ${var}
wang

2.2 高级变量用法 - 有类型变量

Shell变是一般是无类型的,但是bash Shell提供了declare和typeset两个命令用于指定变量的类型,两个命令是等价的。

declare [选项] 变量名 选项: -r 声明或显示只读变量 -i 将变量定义为整型数 -a 将变量定义为数组 -A 将变量定义为关联数组 -f 显示已定义的所有函数名及其内容 -F 仅显示已定义的所有函数名 -x 声明或显示环境变量和函数,相当于export -l 声明变量为小写字母 declare -l var=UPPER -u 声明变量为大写字母 declare -u var=lower

范例:

~ declare -l var=KUBESPHERE
~ echo ${var}
kubesphere

~ declare -u var=kubesphere
~ echo ${var}
KUBESPHERE

2.3 变量间接引用

2.3.1 eval 命令

eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变呈该命令对变量进行两次扫描。是Linux系统的内置命令。

Bash Shell 脚本在执行的时候只会进行一次处理

范例:

~ CMD=whoami
~ echo $CMD
whoami
~ eval echo $CMD
whoami
~ eval $CMD
root

~ n=10;echo {1..$n}
{1..10}
~ n=10;eval echo {1..$n}
1 2 3 4 5 6 7 8 9 10

~ n=5;for i in $(eval echo {1..$n}) ;do echo i=$i;done
i=1
i=2
i=3
i=4
i=5

~ i=a
~ j=1
~ $i$j="hello"
bash: a1=hello: command not found
~ eval $i$j="hello"
~ echo $i$j
a1
~ echo ${a1}
hello

~ i=1 ; j=1 ; arr[$i$j]=x ; echo ${arr[11]};
x
~ i=1 ; j=2 ; arr[$i$j]=y ; echo ${arr[12]};
y

2.3.2 间接变量引用

主要用于复杂的逻辑处理

如果第一个变量的值是第二个变量的名字,从第一个变量引用第二个变量的值就称为间接变量引用
variable1的值是variable2,而variable2又是变量名,variable2的值为value,间接变量引用是指通过variable1获得变量值value的行为。

Bash Shell 默认只处理一次变量赋值。

variable1=variable2
variable2=value

示例:
i=1
$1=wang

bash Shell 提供了两种格式实现间接变量引用

#方法1:
#变量赋值
eval tempvar=\$$variable1
#显示值
eval echo \$$variable1
eval echo '$'$variable1

#方法2:
#变量赋值
tempvar=${!variable1}
#显示值
echo ${!variable1}

范例:

#$$表示当前shell 的进程编号
echo $$

~ ceo=name
~ name=zhong
~ echo $ceo
name
~ echo $$ceo
25585ceo
~ echo \$$ceo
$name
或者
~ echo '$'$ceo
$name

~ eval echo '$'$ceo
zhong
~ eval echo \$$ceo
zhong
~ echo ${!ceo}
zhong

范例:

~ N1=N2
~ N2=zhongzhiwei
~ eval NAME=\$$N1
~ echo $NAME
zhongzhiwei

~ NAME=${!N1}
~ echo $NAME
zhongzhiwei

范例:批量创建用户

~ vim create-eval-useradd.sh
#!/bin/bash

n=$#
[ $n -eq 0 ] && { echo "Usgae: `basename $0` username..."; exit 2; }

#eval echo {1..$n}中的eval用来将$n转变为数值后进行{1..n}
for i in $(eval echo {1..$n}) ;do
  #echo $i;user=${i}
  #user=$i 若直接引用$i,那么i的值就直接是{1..n}的数值,而数值背后的位置参数并没有引用。所以需要变量引用
  user=${!i}    #user=$(eval echo \$${i}) --> user=${${i}}类似
  id $user &> /dev/null && \
  echo "$user is exist" || \
  { useradd $user; echo "$user is created"; }
done

~ chmod +x create-eval-useradd.sh
~ ./create-eval-useradd.sh kubesphere kubernetes kubeedge

2.3.3 变量引用 reference

主要用于复杂的逻辑处理

~ cat reference-test.sh
#!/bin/bash
ceo=zhongzhiwei
title=ceo

declare -n ref=$title
[ -R ref ] && echo "reference"    #[ -R var ] 是bash4.4的新特性
echo $ref
ceo=kubernetes
echo $ref

~ bash reference-test.sh
reference
zhongzhiwei
kubernetes