如何在 shell 中的变量中 keep/remove 数字?
How to keep/remove numbers in a variable in shell?
我有一个变量,例如:
disk=/dev/sda1
我要提取:
- 只有非数字部分(即/dev/sda)
- 只有数字部分(即 1)
我将在需要磁盘和分区号的脚本中使用它。
我怎样才能在 shell(主要是 bash 和 zsh)中做到这一点?
我正在考虑在文档中使用 Shell parameters expansions, but couldn't find working patterns。
基本上,我试过:
echo ${disk##[:alpha:]}
和
echo ${disk##[:digit:]}
但是 none 起作用了。两者都返回 /dev/sda1
扩展 kind-of 的工作方式正好相反。使用 [:digit:]
您将只匹配一个数字。您需要匹配直到或从数字开始的所有内容,因此您需要使用 *
.
以下看起来不错:
$ echo ${disk%%[0-9]*} ${disk##*[^0-9]}
/dev/sda 1
要使用 [:digit:]
你需要双括号,因为字符 class 是 [:class:]
并且它本身必须在 [
]
内。这就是为什么我更喜欢 0-9
,少打字*。以下同上:
echo ${disk%%[[:digit:]]*} ${disk##*[^[:digit:]]}
* - 理论上它们可能不相等,因为 [0-9]
会受到当前语言环境的影响,所以它可能不等于 [0123456789]
,但会有所不同。
使用 bash 和 zsh 以及参数扩展:
disk="/dev/sda12"
echo "${disk//[0-9]/} ${disk//[^0-9]/}"
输出:
/dev/sda 12
在参数替换中使用模式时必须小心。这些模式不是正则表达式,而是路径名扩展模式或 glob 模式。
想法是删除最后一个数字,因此您想利用删除匹配的后缀模式 (${parameter%%word}
)。这里我们删除了 word
描述的匹配模式的最长实例。使用模式 [0-9]
可以轻松表示单个数字,但是 multi-digit 数字更难。为此,您需要使用扩展的 glob 表达式:
*(pattern-list)
: Matches zero or more occurrences of the given patterns
所以如果你想删除最后一个数字,你使用:
$ 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
我有一个变量,例如:
disk=/dev/sda1
我要提取:
- 只有非数字部分(即/dev/sda)
- 只有数字部分(即 1)
我将在需要磁盘和分区号的脚本中使用它。 我怎样才能在 shell(主要是 bash 和 zsh)中做到这一点?
我正在考虑在文档中使用 Shell parameters expansions, but couldn't find working patterns。
基本上,我试过:
echo ${disk##[:alpha:]}
和
echo ${disk##[:digit:]}
但是 none 起作用了。两者都返回 /dev/sda1
扩展 kind-of 的工作方式正好相反。使用 [:digit:]
您将只匹配一个数字。您需要匹配直到或从数字开始的所有内容,因此您需要使用 *
.
以下看起来不错:
$ echo ${disk%%[0-9]*} ${disk##*[^0-9]}
/dev/sda 1
要使用 [:digit:]
你需要双括号,因为字符 class 是 [:class:]
并且它本身必须在 [
]
内。这就是为什么我更喜欢 0-9
,少打字*。以下同上:
echo ${disk%%[[:digit:]]*} ${disk##*[^[:digit:]]}
* - 理论上它们可能不相等,因为 [0-9]
会受到当前语言环境的影响,所以它可能不等于 [0123456789]
,但会有所不同。
使用 bash 和 zsh 以及参数扩展:
disk="/dev/sda12"
echo "${disk//[0-9]/} ${disk//[^0-9]/}"
输出:
/dev/sda 12
在参数替换中使用模式时必须小心。这些模式不是正则表达式,而是路径名扩展模式或 glob 模式。
想法是删除最后一个数字,因此您想利用删除匹配的后缀模式 (${parameter%%word}
)。这里我们删除了 word
描述的匹配模式的最长实例。使用模式 [0-9]
可以轻松表示单个数字,但是 multi-digit 数字更难。为此,您需要使用扩展的 glob 表达式:
*(pattern-list)
: Matches zero or more occurrences of the given patterns
所以如果你想删除最后一个数字,你使用:
$ 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