如何在外壳中的变量中保留/删除数字?

时间:2019-06-16 17:17:55

标签: bash zsh parameter-expansion

我有一个变量,例如:

disk=/dev/sda1

我要提取:

  • 仅非数字部分(即/ dev / sda)
  • 仅数字部分(即1)

我将在需要磁盘和分区号的脚本中使用它。 我该如何在Shell(主要是bash和zsh)中做到这一点?

我当时正在考虑使用Shell parameters expansions,但是在文档中找不到patterns的工作。

我基本上尝试过:

echo ${disk##[:alpha:]}

echo ${disk##[:digit:]}

但是没有一个起作用。都返回了/dev/sda1

3 个答案:

答案 0 :(得分:3)

使用bash和zsh以及参数扩展:

disk="/dev/sda12"
echo "${disk//[0-9]/} ${disk//[^0-9]/}"

输出:

/dev/sda 12

答案 1 :(得分:1)

扩展工作是相反的。使用[:digit:],您将只匹配一位数字。您需要对所有内容进行匹配,直到或从一个数字开始,所以您需要使用*

以下内容看起来不错:

$ echo ${disk%%[0-9]*} ${disk##*[^0-9]}
/dev/sda 1

要使用[:digit:],您需要使用大括号,因为字符类为[:class:],而字符类本身必须位于[ ]内。这就是为什么我更喜欢0-9而不用键入*的原因。以下与上面相同:

echo ${disk%%[[:digit:]]*} ${disk##*[^[:digit:]]}

*-从理论上讲,它们可能不相等,因为[0-9]可能受当前区域设置的影响,因此它可能不等于[0123456789],而是不同的东西。

答案 2 :(得分:1)

在参数替换中使用模式时必须小心。这些模式不是正则表达式,而是路径名扩展模式或全局模式。

这个想法是删除最后一个数字,因此您想使用删除匹配的后缀模式${parameter%%word})。在这里,我们删除word描述的匹配模式的最长实例。通过使用模式[0-9]可以很容易地表示一位数字,但是,多位数字更难。为此,您需要使用扩展的全局表达式:

  

*(pattern-list)匹配零个或多个出现的给定模式

因此,如果要删除最后一个号码,请使用:

$ shopt -s extglob
$ disk="/dev/sda1"
$ echo "${disk#${disk%%*([0-9])}} "${disk%%*([0-9])}"
1 dev/sda
$ disk="/dev/dsk/c0t2d0s0"
$ echo "${disk#${disk%%*([0-9])}} "${disk%%*([0-9])}"
0 /dev/dsk/c0t2d0s

我们必须使用${disk#${disk%%*([0-9])}}删除前缀。实际上,它搜索最后一个数字,将其删除,使用剩余的数字,然后再次删除该部分。

您还可以将模式替换${parameter/pattern/string})与锚点%#结合使用,以将模式锚定到参数。 (有关更多信息,请参见man bash)。这完全等同于先前的解决方案:

$ shopt -s extglob
$ disk="/dev/sda1"
$ echo "${disk/${disk/%*([0-9])}/}" "${disk/%*([0-9])}"
1 dev/sda
$ disk="/dev/dsk/c0t2d0s0"
$ echo "${disk/${disk/%*([0-9])}/}" "${disk/%*([0-9])}"
0 /dev/dsk/c0t2d0s