我有一个试图从gparted获取信息块的脚本。
我的数据如下:
Disk /dev/sda: 42.9GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system Flags
1 1049kB 316MB 315MB primary ext4 boot
2 316MB 38.7GB 38.4GB primary ext4
3 38.7GB 42.9GB 4228MB primary linux-swap(v1)
log4net.xml
Model: VMware Virtual disk (scsi)
Disk /dev/sdb: 42.9GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system Flags
1 1049kB 316MB 315MB primary ext4 boot
5 316MB 38.7GB 38.4GB primary ext4
6 38.7GB 42.9GB 4228MB primary linux-swap(v1)
我使用正则表达式将其分成两个磁盘块
^ Disk(/ dev [\ S] +):((?!Disk)[\ s \ S])*
这适用于多线上。
当我在bash脚本中测试时,我似乎无法匹配\ s或\ S - 我做错了什么?
我正在通过以下脚本对此进行测试:
data=`cat disks.txt`
morematches=1
x=0
regex="^Disk (/dev[\S]+):((?!Disk)[\s\S])*"
if [[ $data =~ $regex ]]; then
echo "Matched"
while [ $morematches == 1 ]
do
x=$[x+1]
if [[ ${BASH_REMATCH[x]} != "" ]]; then
echo $x "matched" ${BASH_REMATCH[x]}
else
echo $x "Did not match"
morematches=0;
fi
done
fi
但是,当我逐步测试正则表达式的部分时,每当我匹配\ s或\ S时,它都不起作用 - 我做错了什么?
答案 0 :(得分:22)
可能不支持\ S和\ s,或者您不能将它们放在[ ]
周围。请尝试使用此格式:
^Disk[[:space:]]+/dev[^[:space:]]+:[[:space:]]+[^[:space:]]+
修改强>
看起来你真的想要得到匹配的字段。我使脚本更简单,但我不确定它是否是你想要的输出:
#!/bin/bash
regex='^Disk[[:space:]]+(/dev[^[:space:]]+):[[:space:]]+(.*)'
while read line; do
[[ $line =~ $regex ]] && echo "${BASH_REMATCH[1]} matches ${BASH_REMATCH[2]}."
done < disks.txt
哪个产生
/dev/sda matches 42.9GB.
/dev/sdb matches 42.9GB.
答案 1 :(得分:3)
来自man bash
可以使用另外的二元运算符=〜 优先级为==和!=。使用时,右边的字符串 操作员是 支持扩展正则表达式并相应匹配(如在regex(3)中)。
ERE不支持预测/后退。但是,您可以在代码中使用它们((?!Disk)
)。
这就是为什么你的正则表达式不会像你预期的那样匹配的原因。
答案 2 :(得分:3)
因为这是一个常见的常见问题解答,让我列出一些Bash不支持的构造,以及如何解决它们,其中有一个简单的解决方法。
常用的正则表达式有多种方言。 Bash支持的是扩展正则表达式的变体。这不同于例如许多在线正则表达式测试人员支持,这通常是更现代的Perl 5 / PCRE变体。
\d
\D
\s
\S
\w
\W
- 这些可以替换为等值的POSIX字符类{分别为{1}},[[:digit:]]
,[^[:digit:]]
,[[:space:]]
,[^[:space:]]
和[_[:alnum:]]
。 (注意最后一种情况,其中[^_[:alnum:]]
POSIX字符类使用下划线进行扩充,以完全等同于Perl [:alnum:]
简写。)\w
替换a.*?b
以在实践中获得类似的效果,尽管两者并不完全相同。a[^ab]*b
或(?<=before)
等内容,实际上(?!after)
的任何内容都是Perl扩展。这些问题没有简单的一般解决方法,但您可以经常将问题重新划分为可以避免外观的问题。答案 3 :(得分:2)
我知道你已经“解决了”这个问题,但你原来的问题可能就像你在测试中引用$regex
一样简单。即:
if [[ $data =~ "$regex" ]]; then
Bash变量扩展只会在字符串中填充,而原始正则表达式中的空格将会破坏测试,因为:
regex="^Disk (/dev[\S]+):((?!Disk)[\s\S])*"
if [[ $data =~ $regex ]]; then
相当于:
if [[ $data =~ ^Disk (/dev[\S]+):((?!Disk)[\s\S])* ]]; then
和bash / test将有一个有趣的时间来解释奖金参数和所有那些未加引号的元字符。
请记住,bash不会传递变量,会扩展它们。
答案 4 :(得分:0)
此外,[\s\S]
相当于.
,即任何字符。在我的shell上,[^\s]
有效,但不是[\S]
。