Shell字符串处理

Shell中判断字符串包含关系

通过grep来判断

1
2
3
4
5
6
7
8
9
str1="abcdefgh"
str2="def"
result=$(echo $str1 | grep "${str2}")
if [[ "$result" != "" ]]
then
echo "包含"
else
echo "不包含"
fi

先打印长字符串,然后在长字符串中 grep 查找要搜索的字符串,用变量result记录结果,如果结果不为空,说明str1包含str2。如果结果为空,说明不包含。这个方法充分利用了grep 的特性,最为简洁。

字符串运算符

1
2
3
4
5
6
7
8
str1="abcdefgh"
str2="def"
if [[ $str1 =~ $str2 ]]
then
echo "包含"
else
echo "不包含"
fi

利用字符串运算符 =~ 直接判断str1是否包含str2。

利用通配符

1
2
3
4
5
6
7
8
str1="abcdefgh"
str2="def"
if [[ $str1 == *$str2* ]]
then
echo "包含"
else
echo "不包含"
fi

用通配符*号代理str1中非str2的部分,如果结果相等说明包含,反之不包含。

利用case in 语句

1
2
3
4
5
6
str1="abcdefgh"
str2="def"
case $str1 in
*"$str2"*) echo Enemy Spot ;;
*) echo nope ;;
esa

利用替换

1
2
3
4
5
6
7
8
str1="abcdefgh"
str2="def"
if [[ ${str1/${str2}//} == $str1 ]]
then
echo "不包含"
else
echo "包含"
fi

字符串替换

基于Pattern Matching的子串替换

替换第一个:

1
${STR/$OLD/$NEW}

替换所有:

1
${STR//$OLD/$NEW}

替换开头。如果STR以OLD串开头,则替换:

1
${STR/#$OLD/$NEW}

替换结尾。如果STR以OLD串结尾,则替换:

1
${STR/%$OLD/$NEW}

注意:不能使用正则表达式,只能使用?的Shell扩展。只能用shell通配符如 ? [list] [!list] [a-z]。

​ 如果被替换串包含/字符,那么要转义,写成\/。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[user@psvmc ~]# STR="Hello World" 
[user@psvmc ~]# echo ${STR/o/O}
HellO World
[user@psvmc ~]# echo ${STR//o/O}
HellO WOrld
[user@psvmc ~]# STR="Hello World"
[user@psvmc ~]# echo ${STR/#He/he}
hello World
[user@psvmc ~]# echo ${STR/#o/he}
Hello World
[user@psvmc ~]# echo ${STR/%He/he}
Hello World
[user@psvmc ~]# echo ${STR/%ld/lD}
Hello WorlD

使用sed命令实现正则表达式替换

1
echo "$STR" | sed "s/$OLD/$NEW/"

将STR中的OLD子串替换成NEW。

示例:

1
2
3
4
5
6
7
[user@psvmc ~]# STR="123456789"
[user@psvmc ~]# echo "$STR" | sed s/345/OK/
12OK6789
[user@psvmc ~]# OLD=345
[user@psvmc ~]# NEW=OK
[user@psvmc ~]# echo "$STR" | sed "s/$OLD/$NEW/"
12OK6789

使用tr命令实现字符集合的替换

使用tr命令可以实现字符的替换,并且可以是从一批字符到另一批字符的替换。比如小写字母变成大写字母,或者反过来。

1
2
[user@psvmc ~]# echo "bash" | tr "[a-z]" "[A-Z]"
BASH

字符串删除

基于Pattern Matching的子串删除

子串删除是一种特殊的替换

将STR中第一个SUB子串删除:

1
${STR/$SUB}

将STR中所有SUB子串删除:

1
${STR//$SUB}

去头,从开头去除最短匹配前缀:

1
${STR#$PREFIX}

去头,从开头去除最长匹配前缀:

1
${STR##$PREFIX}

去尾,从结尾去除最短匹配后缀:

1
${STR%$SUFFIX}

去尾,从结尾去除最长匹配后缀:

1
${STR%%$SUFFIX}

注意:经常会记错#%的含义,有一个帮助记忆的方法
看一下键盘,#$之前,%$之后,就知道#去头,%去尾。

注意:不能使用正则表达式,只能使用?*的Shell扩展。

示例:获取字符串的前缀和后缀

1
2
3
4
5
6
7
8
file_path='aa.jpg'
# 文件名 aa
# 以最后一个字符.向后删除
echo ${file_path%.*}

# 文件后缀 jpg
# 以最后一个字符.向前删除
echo ${file_path##*.}

路径字符串的处理

取目录部分:

1
dirname ${FULLPATH}

取文件名部分:

1
basename ${FULLPATH}

取文件名部分,并且去掉指定的扩展名:

1
basename {FULLPATH} {EXT}

示例:

1
2
3
4
5
6
7
8
9
10
11
[user@psvmc ~]# FULLPATH=/user/work/project/backup.tar.gz 
[user@psvmc ~]# dirname "$FULLPATH"
/user/work/project
[user@psvmc ~]# basename "$FULLPATH"
backup.tar.gz
[user@psvmc ~]# basename "$FULLPATH" .gz
backup.tar
[user@psvmc ~]# basename "$FULLPATH" .tar
backup.tar.gz
[user@psvmc ~]# basename "$FULLPATH" .tar.gz
backup

取目录部分:

1
2
3
${FULLPATH%/*} 
# 或者
dirname "$FULLPATH"

取文件名称:

1
2
3
FILE=${FULLPATH##*/}
# 或者
basename "$FULLPATH"

取最短基本名称:

1
${FILE%%.*}

取最长基本名称:

1
${FILE%.*}

取最短扩展名:

1
2
3
${FILE##*.}  
# 或者
${FULLPATH##*.}

取最长扩展名:

1
2
3
${FILE#*.} 
# 或者
${FULLPATH#*.}

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[user@psvmc ~]# FULLPATH=/user/work/project/backup.tar.gz 
[user@psvmc ~]# echo ${FULLPATH%/*}
/user/work/project
[user@psvmc ~]# dirname "$FULLPATH"
/user/work/project

[user@psvmc ~]# FILE=${FULLPATH##*/}
[user@psvmc ~]# echo $FILE
backup.tar.gz
[user@psvmc ~]# basename "$FULLPATH"
backup.tar.gz

[user@psvmc ~]# echo ${FILE%%.*}
backup
[user@psvmc ~]# echo ${FILE%.*}
backup.tar

[user@psvmc ~]# echo ${FILE##*.}
gz
[user@psvmc ~]# echo ${FILE#*.}
tar.gz