我怎么摆脱这个“(”使用正则表达式?

时间:2011-01-06 08:27:03

标签: regex perl

我正在前进一个正则表达式,我遇到了一个似乎无法绕过的路障。我试图摆脱“(”在使用正则表达式的文本行的中间,有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位)部分。

5 个答案:

答案 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更容易阅读,因为这允许间距和注释。