我正在前进一个正则表达式,我遇到了一个似乎无法绕过的路障。我试图摆脱“(”在使用正则表达式的文本行的中间,有2但我想出了如何在行的末尾获得一个。它在中间的那个我可以破解
以下是我正在搜索的文件的更完整摘录。
ide1:0.present = "TRUE"
ide1:0.clientDevice = "TRUE"
ide1:0.deviceType = "cdrom-raw"
ide1:0.startConnected = "FALSE"
floppy0.startConnected = "FALSE"
floppy0.clientDevice = "TRUE"
ethernet0.present = "TRUE"
ethernet0.virtualDev = "e1000"
ethernet0.networkName = "solignis.local"
ethernet0.addressType = "generated"
guestOSAltName = "Ubuntu Linux (64-bit)"
guestOS = "ubuntulinux"
uuid.location = "56 4d e8 67 57 18 67 04-c8 68 14 eb b3 c7 be bf"
uuid.bios = "56 4d e8 67 57 18 67 04-c8 68 14 eb b3 c7 be bf"
vc.uuid = "52 c7 14 5c a0 eb f4 cc-b3 69 e1 6d ad d8 1a e7"
这是我正在处理的整个foreach循环。
my @virtual_machines;
foreach my $vm (keys %virtual_machines) {
push @virtual_machines, $vm;
}
foreach my $vm (@virtual_machines) {
my $vmx_file = $ssh1->capture("cat $virtual_machines{$vm}{VMX}");
if ($vmx_file =~ m/^\bguestOSAltName\b\s+\S\s+\W(?<GUEST_OS> .+[^")])\W/xm) {
$virtual_machines{$vm}{"OS"} = "$+{GUEST_OS}";
} else {
$virtual_machines{$vm}{"OS"} = "N/A";
}
if ($vmx_file =~ m/^\bguestOSAltName\b\s\S\s.+(?<ARCH> \d{2}\W\bbit\b)/xm) {
$virtual_machines{$vm}{"Architecture"} = "$+{ARCH}";
} else {
$virtual_machines{$vm}{"Architecture"} = "N/A";
}
}
我在想这个问题是我无法匹配“(”因为之前的表达式是“。+”所以它匹配文本行中的所有内容,不管是字母数字还是空格,甚至是像hypens的符号
我有什么想法可以让它发挥作用吗?
这是我从哈希转储输出的结果。
$VAR1 = {
'NS02' => {
'ID' => '144',
'Version' => '7',
'OS' => 'Ubuntu Linux (64-bit',
'VMX' => '/vmfs/volumes/datastore2/NS02/NS02.vmx',
'Architecture' => '64-bit'
},
我正在使用ARCH工作的代码块的部分完美无缺,所以我真正需要的是破解“(64位)”部分,如果搜索进入时存在(并且删除了前面的部分) (。
之前的空白)我想要的是将上面的哈希转储转换成这个。
$VAR1 = {
'NS02' => {
'ID' => '144',
'Version' => '7',
'OS' => 'Ubuntu Linux',
'VMX' => '/vmfs/volumes/datastore2/NS02/NS02.vmx',
'Architecture' => '64-bit'
},
相同的东西减去(64位)部分。
答案 0 :(得分:3)
您可以将正则表达式简化为/^guestOSAltName\s+=\s+"(?<GUEST_OS>.+)"/m
。这是做什么的:
^
强制匹配从一行的开头guestOSAltName
是字符串文字。\s+
匹配1个或多个空格字符。(?<GUEST_OS>.+)
匹配从空格后到行尾的所有文本,捕获该组并将其命名为GUEST_OS
。如果该行可以有评论,您可能希望将.+
更改为[^#]+
。"
是字面引号。m
会启用多行匹配。代码:
if ($vmx_file =~ /^guestOSAltName\s+=\s+"(?<GUEST_OS>.+)"/m) {
print "$+{GUEST_OS}";
} else {
print "N/A";
}
请在此处查看:http://ideone.com/1xH5J
答案 1 :(得分:2)
所以你想在guestOSAltName
之后匹配({并且不包括)第一个(
的字符串内容(如果存在)?
然后用
替换代码示例的第一行if ($vmx_file =~ m/^guestOSAltName\s+=\s+"(?<GUEST_OS>[^"()]+)/xm) {
如果在潜在的左括号之前总是有空白字符,那么您可以使用
if ($vmx_file =~ m/^guestOSAltName\s+=\s+"(?<GUEST_OS>[^"()]+)[ "]/xm) {
因此,如果存在,则不需要去除尾随空格。
答案 2 :(得分:0)
这样的事情应该有效:
$match =~ s/^(.*?)\((.*?)$/$1$2/;
答案 3 :(得分:0)
在柜台后面使用?
。 ?
代表non greedy。
正则表达式为/^guestOSAltName[^"]+"(?<GUEST_OS>.+?)\s*[\("]+.*$/
:
#!/usr/bin/env perl
foreach my $x ('guestOSAltName = "Ubuntu Linux (64-bit)"', 'guestOSAltName = "Microsoft Windows Server 2003, Standard Edition"') {
if ($x =~ m/^guestOSAltName[^"]+"(?<GUEST_OS>.+?)\s*[\("]+.*$/xm) {
print "$+{GUEST_OS}\n";
} else {
print "N/A\n";
}
if ($x =~ m/^guestOSAltName[^(]+\((?<ARCH>\d{2}).*/xm) {
print "$+{ARCH}\n";
} else {
print "N/A\n";
}
}
开始演示:
$ perl t.pl
Ubuntu Linux
64
Microsoft Windows Server 2003, Standard Edition
N/A
答案 4 :(得分:0)
一般发现.*
太强大了(正如你所发现的那样!)。两个建议
更明确地了解您的目标
my $text = '( something ) ( something else) ' ;
$text =~ /
\(
( [\s\w]+ )
\)
/x ;
print $1 ;
使用非贪婪匹配
my $text = '( something ) ( something else) ' ;
$text =~ /
\(
( .*? ) # non greedy match
\)
/x ;
print $1 ;
一般观察 - 如果您使用/x
选项,则涉及的regexp更容易阅读,因为这允许间距和注释。