Вложенный цикл while, который, кажется, не хранит переменные должным образом - PullRequest
3 голосов
/ 11 апреля 2011

Я замечательный Perl-кодер, и у меня много проблем с выяснением причины этой конкретной проблемы. Кажется, что это переменная проблема.

sub patch_check {
  my $pline;
  my $sline;
  while (<SYSTEMINFO>) {
    chomp($_);
    $sline = $_;

    while (<PATCHLIST>) {
      chomp($_);
      $pline = $_;
      print "sline $sline pline $pline underscoreline $_ "; #troubleshooting

      print "$sline - $pline\n";
      if ($pline =~ /($sline)/) {
        #print " - match $pline -\n";
      }
    } #end while
  }
}

Есть еще код, но я не думаю, что он уместен. Когда я печатаю $ sline в первом цикле, он работает нормально, но не во втором цикле. Я попытался сделать переменные глобальными, но это тоже не сработало.

Суть подчиненной формы заключается в том, что я хочу открыть файл (исправления) и посмотреть, находится ли он в (systeminfo). Я также пытался читать файлы в массивы и делать циклы foreach.

У кого-нибудь есть другое решение?

Ответы [ 4 ]

4 голосов
/ 11 апреля 2011

Похоже, ваша настоящая цель - найти строки в обоих файлах, верно? Нормальный (и гораздо более эффективный! - он требует, чтобы вы читали в каждом файле только один раз, а не читали все по одному файлу для каждой строки в другой), чтобы сделать это в Perl, это прочитать строки из одного файла в хэш, затем используйте поиск хеша в каждой строке в другом файле, чтобы проверить совпадения.

Непроверенный (но такой простой должен работать) код:

sub patch_check {
  my %slines;
  while (<SYSTEMINFO>) {
    # Since we'll just be comparing one file's lines
    # against the other file's lines, there's no real
    # reason to chomp() them
    $slines{$_}++;
  }
  # %slines now has all lines from SYSTEMINFO as its
  # keys and the values are the number of times the
  # line appears, in case that's interesting to you

  while (<PATCHLIST>) {
    print "match: $_" if exists $slines{$_};
  }
}

Кстати, если вы читаете ваши данные из SYSTEMINFO и PATCHLIST, то вы делаете это старомодным способом. Если у вас есть шанс, прочитайте лексические файловые дескрипторы и форму с тремя аргументами open, если вы еще не знакомы с ними.

3 голосов
/ 11 апреля 2011

Ваш код не входит в цикл PATCHLIST во второй раз во время цикла SYSTEMINFO while, потому что вы уже прочитали все содержимое PATCHLIST в первый раз. Вам придется заново открыть файловый дескриптор PATCHLIST, чтобы выполнить то, что вы пытаетесь сделать.

Это довольно неэффективный способ проверить, соответствуют ли строки одного файла строкам другого файла. Посмотрите на grep с флагом -f для другого способа.

grep -f PATCHFILE SYSTEMINFO
2 голосов
/ 11 апреля 2011

Что мне нравится делать в таких случаях: читать один файл и создавать ключи для хэша из значений, которые вы ищете. А затем прочитайте второй файл и посмотрите, существуют ли уже ключи. Таким образом, вы должны прочитать каждый файл только один раз.

Вот пример кода, не проверенный:

sub patch_check {
    my %patches = ();

    open(my $PatchList, '<', "patch.txt") or die $!;
    open(my $SystemInfo, '<', "SystemInfo.txt") or die $!;

    while ( my $PatchRow = <$PatchList> ) {
        $patches($PatchRow) = 0;
    }

    while ( my $SystemRow = <$SystemInfo> ) {
        if exists $patches{$SystemRow} {
            #The Patch is in System Info
            #Do whateever you want
        }
    }
}
0 голосов
/ 11 апреля 2011

Вы не можете прочитать один файл внутри цикла чтения другого. Прибавьте один файл, затем сделайте один цикл в качестве строки foreach для файла с блупами, внешнего цикла, цикла чтения.

...