Как мне избавиться от этого "(" с помощью регулярных выражений? - PullRequest
1 голос
/ 06 января 2011

Я двигался с выражением регулярного выражения, и я наткнулся на блокпост, который, кажется, не могу обойти. Я пытаюсь избавиться от "(" в середине строки текста с помощью регулярных выражений, их было 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 ]

3 голосов
/ 06 января 2011

Вы можете упростить свое регулярное выражение до /^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

2 голосов
/ 06 января 2011

Таким образом, вы хотите сопоставить содержимое строки после guestOSAltName вплоть до (и не включая) первого (, если присутствует?

Затем замените первую строку вашего примера кода на

if ($vmx_file =~ m/^guestOSAltName\s+=\s+"(?<GUEST_OS>[^"()]+)/xm) {

Если перед потенциальной открывающей скобкой всегда есть символ пробела, вы можете использовать

if ($vmx_file =~ m/^guestOSAltName\s+=\s+"(?<GUEST_OS>[^"()]+)[ "]/xm) {

, поэтому вам не нужно удалять пробельные символы, если они есть.

0 голосов
/ 06 января 2011

Как правило, вы обнаружите, что .* слишком мощный (как вы находите!).Два предложения

Будьте более точными в том, что вы ищете

    my $text = '( something ) ( something else) ' ;

    $text =~ /
      \(
      ( [\s\w]+ )
      \)
        /x ;

    print $1 ;

Используйте не жадное сопоставление

    my $text = '( something ) ( something else) ' ;

    $text =~ /
      \(
      ( .*? )   # non greedy match
      \)
        /x ;

    print $1 ;

Общее наблюдение - регулярные выражения гораздо проще читать, еслиВы используете опцию /x, так как это позволяет интервалы и комментарии.

0 голосов
/ 06 января 2011

Используйте ? за прилавком.? обозначает не жадный .

Регулярное выражение: /^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
0 голосов
/ 06 января 2011

Примерно так должно работать:

$match =~ s/^(.*?)\((.*?)$/$1$2/;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...