我有一个变量,例如:
disk=/dev/sda1
我要提取:
我将在需要磁盘和分区号的脚本中使用它。 我该如何在Shell(主要是bash和zsh)中做到这一点?
我当时正在考虑使用Shell parameters expansions,但是在文档中找不到patterns的工作。
我基本上尝试过:
echo ${disk##[:alpha:]}
和
echo ${disk##[:digit:]}
但是没有一个起作用。都返回了/dev/sda1
答案 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