利用正则表达式,我们可以对字符串进行一些高级操作,今天我们就介绍一个在shell脚本中听常用的一种处理字符串的方法——字符串的删除。

命令格式:

  • ${variable#delete_part}
  • ${variable##delete_part}
  • ${variable%delete_part}
  • ${variable%%delete_part}

我们以第一条命令做说明,可以看到,删除命令共分为四部分:

  1. "$":是这种删除模式的关键字,必不可少。
  2. "variable":是我们要操作的变量。需要注意的是,这种删除并不会改变变量本身的值。
  3. "#": 这个是删除的模式,一个#代表“从变量内容的最前面开始向右删除,且仅删除最短的那个”;两个#(##),代表“从变量内容的最前面开始向右删除,且删除最长的那个”。一个%代表“从变量内容的最后面开始向左删除,且仅删除最短的那个”;两个%(%%)代表:“从变量内容的最后面开始向右删除,且删除最长的那个”。具体含义见后面的例子。
  4. "delete_part":代表要删除的部分,这部分会在要操作的变量中进行匹配,匹配成功的就会被删除。这里可以使用正则表达式。

下面我们用几个例子来看这个命令的具体使用:

首先我们将环境变量PATH赋给临时变量path,然后用path来进行练习:

注:下面的"allan@ubuntu:~$"均为终端提示符。

allan@ubuntu:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
allan@ubuntu:~$ path=$PATH
allan@ubuntu:~$ echo $path
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

Exp 1:假如我们要删除“/usr/local/sbin:”这个路径,可以如下操作:

allan@ubuntu:~$ echo ${path#/*sbin:}
/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

这里我们使用了通配符*,代表0个或任意多个任意字符。上面那句命令的意思就是从变量最前面开始往右匹配最短的“/*sbin:”这个字符串, 很明显,就是“/usr/local/sbin:”这个字符串匹配成功。所以被删除。

Exp 2:现在我们将Exp1中的一个#换成两个#,看一下结果:

allan@ubuntu:~$ echo ${path##/*sbin:}
/bin:/usr/games:/usr/local/games

可以看到两个#的时候,删除的部分是“/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:”,也即从字符串前面往右匹配“/*sbin:”最长的字符串。这便是#和##的区别,一个是匹配最短的,一个是匹配最长的。

%、%%与#、##对应含义类似,不过是从变量最后面开始往左匹配,%代表最短匹配,%%代表最长匹配。看下面这个例子:

Exp 3:使用%和%%的例子

allan@ubuntu:~$ echo ${path%:/usr*}
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
allan@ubuntu:~$ echo ${path%%:/usr*}
/usr/local/sbin

从上面的三个例子可以看出这个命令还是蛮好用的,现在大家可能会疑问这个命令用在哪里呢?其实这个命令的应用范围应该蛮广的,不过在目录分离方面用的最多,下面就介绍一个应用特别多的场景:

比如我的邮件目录是/var/spool/mail/allan,现在我想得到最后的那个用户名allan,可以如下操作:

allan@ubuntu:~$ echo $MAIL
/var/spool/mail/allan
allan@ubuntu:~$ echo ${MAIL##*/}
allan

相反,现在我们不想要用户名,只想得到邮件目录/var/spool/mail,可以如下操作:

allan@ubuntu:~$ echo $MAIL
/var/spool/mail/allan
allan@ubuntu:~$ echo ${MAIL%/*}
/var/spool/mail

这两个操作在平时我们写shell脚本的时候还是经常会用到的。关于字符串的删除就介绍这些。