Почему мой perl-скрипт ведет себя по-разному, если я запускаю его из значка, а не из командной строки?

Это всего лишь второй сценарий Perl, который я написал, поэтому буду очень признателен за любую конструктивную помощь/совет. Также обратите внимание, что я работаю на компьютере с Windows, используя Strawberry Perl. Я знаю, что для Perl существует модуль Tidy, но (по причинам, которые не стоит объяснять в этой заметке) я бы предпочел вызывать tidy.exe из сценария, а не использовать модуль.

Что я хочу, чтобы мой perl-скрипт делал:

  1. Возьмите html-файл, скопируйте его и присвойте ему расширение .xml.

  2. Запустите tidy.exe для только что сформированного XML-файла, чтобы преобразовать его в правильно сформированный xml.

  3. Удалите пространство имен xhtml из вновь созданного правильно сформированного XML-файла.

Когда я запускаю его из командной строки, используя следующую команду G:\TestFolder>perl tidy_cleanup.pl, он дает желаемый результат. Однако, когда я запускаю скрипт из значка, он пропускает шаг 2, указанный выше. Основываясь на приведенном ниже коде, у вас есть идеи, почему он ведет себя таким образом?

Вот мой код:

#!/usr/bin/perl

use strict;
use warnings;

use File::Basename;
use FileHandle;

my $basename;
my @files = glob("*.html");

foreach my $file (@files) {

  my $oldext   = ".html";
  my $newext   = ".xml";
  my $newerext = "v2.xml";

  my $newfile  = $file;
  $newfile     =~ s/$oldext/$newext/;

  my $newerfile = $newfile;
  $newerfile    =~ s/$newext/$newerext/;

  open IN, $file or die "Can't read source file $file: $\n";
  open OUT, ">$newfile" or die "Can't write on file $newfile: $!\n";

  print "Copying $file to $newfile\n";


{while(<IN>)

{  
print OUT $_;  

close(IN);
close(OUT);


}

my $xmltidy = "for \%i in ($newfile) do c:\\Tidy\\tidy.exe --output-xml yes --numeric-entities yes --doctype omit --quote-nbsp no -asxml -utf8 -numeric -m \"\%i\"";
system($xmltidy);


print "\nfinished running tidy \n\n";
}

  {
    open NEWIN,  "$newfile"    or die "Can't read source file $newfile: $!\n";
    open NEWOUT, ">$newerfile" or die "Can't write on file $newerfile: $!\n";

    print "Copying $newfile to $newerfile\n";
    {
      while (<NEWIN>) {
        if ( /(\<html)( xmlns="http:\/\/www.w3.org\/1999\/xhtml" xml:lang="en-GB")(.*)/ ) {
          print NEWOUT "<html$3";
        }
        else {
          print NEWOUT $_;
        }
      }

      close(NEWIN);
      close(NEWOUT);
    }
  }
}

person 1723842    schedule 21.07.2014    source источник
comment
Трудно поверить, что эта программа делает что-то полезное, как бы вы ее ни запускали. Вы закрываете и входной, и выходной файлы внутри первого цикла while, поэтому в $newfile будет скопирована только одна строка. Вы бы видели сообщения об ошибках типа readline() on closed filehandle, так почему же вы не сообщили нам о них? Я предлагаю вам объяснить, что именно должна делать программа, чтобы мы могли помочь вам исправить ее. Кажется, что в этом есть нечто большее, чем вы описали, поскольку первый оператор if должен иметь цель, хотя все, что он, кажется, делает, это удаляет все перед тегом <html>   -  person Borodin    schedule 21.07.2014
comment
Вы правы, я вижу readline() в закрытом дескрипторе файла IN в строке 42.   -  person 1723842    schedule 21.07.2014
comment
новый код для удаленного оператора if   -  person 1723842    schedule 21.07.2014
comment
Что касается того, что я хочу сделать, это объясняется в шагах 1, 2 и 3 выше.   -  person 1723842    schedule 21.07.2014
comment
Мне немного любопытно, похоже, это работает для одного файла, но вы пытаетесь вызвать tidy, я думаю, с циклом пакетного языка, есть ли причина для этого?   -  person dsolimano    schedule 21.07.2014
comment
Ах, а что за команда, аргументы, рабочий каталог для значка?   -  person dsolimano    schedule 21.07.2014
comment
вы говорите о вызове через system($xmltidy); ? (например, используя system();) ? Я сделал это на основе поиска в Google. Как я могу вызвать файл .exe из сценария Perl?   -  person 1723842    schedule 21.07.2014
comment
Я думаю, что причина цикла пакетного пакетного языка заключается в том, что я хочу в конечном итоге запустить эту программу для нескольких html-файлов, а не только для одного html-файла.   -  person 1723842    schedule 21.07.2014
comment
поэтому, прежде чем я написал сценарий perl, для запуска tidy я бы написал для %i в (*.html) do G:\Folderdirectory\path\tidy.exe --output-xml yes --numeric-entities yes --doctype опустить --quote-nbsp no -asxml -utf8 -numeric -m %i   -  person 1723842    schedule 21.07.2014


Ответы (1)


Причина, по которой ваша программа не работает через ярлык, может заключаться в том, что она ищет файлы HTML в неправильном каталоге. Когда вы запускаете perl tidy_cleanup.pl из командной строки, он просматривает ваш текущий рабочий каталог, однако при настройке ярлыка вам нужно указать текущий каталог в поле, отмеченном Start in:.

Однако, как я сказал в своем комментарии, вы обрабатываете только одну строку файла при копировании из HTML в XML, потому что вы закрываете дескрипторы файла внутри цикла while.

Вот как бы я написал то, что я думаю, что вы хотите.

use strict;
use warnings;
use autodie;

use File::Copy 'copy';

my $tidy = 'C:\Tidy\tidy.exe';
die "'tidy.exe' not found" unless -f $tidy;

for my $html_file (glob '*.html') {

  (my $xml_file = $html_file) =~ s/\.html\z/.xml/;
  copy $html_file, $xml_file;

  print qq{Tidying "$xml_file"\n};

  qx{"$tidy" --output-xml yes --numeric-entities yes --doctype omit --quote-nbsp no -asxml -utf8 -numeric -m "$xml_file"};

  print "Finished running tidy\n\n";

  (my $v2_file = $xml_file) =~ s/\.xml\z/_v2.xml/;
  open my $xml_fh,  '<', $xml_file;
  open my $v2_fh,   '>', $v2_file;

  print qq{Copying "$xml_file" to "$v2_file"\n};

  while (<$xml_fh>) {
    s/\s*xmlns="[^"]+"//;
    s/\s*xml:lang="[^"]+"//;
    print $v2_fh $_;
  }

  print "Copy complete\n\n";
}
person Borodin    schedule 21.07.2014
comment
Итак, когда я запускаю это, я получаю: Не могу открыть «*.xml» для чтения: «Недопустимый аргумент» в строке 19 tidy_cleanup.pl. - person 1723842; 21.07.2014
comment
@xslt_user: строка 19 — это оператор print. Если вы добавили в программу строку 19, которая является qx, пожалуйста, расскажите, что вы сделали. Я внес несколько изменений с момента своего первого сообщения, и у вас может быть версия с ошибками, если вы быстро ее подберете. Пожалуйста, сделайте еще одну копию и повторите попытку. - person Borodin; 22.07.2014
comment
Новые изменения, которые вы сделали, сработали. Я также заставил его работать, используя приведенный ниже код. - person 1723842; 22.07.2014
comment
@xslt_user: Хорошо, что ваша программа заработала, но я призываю вас использовать что-то более похожее на мое решение. Структура вашего кода очень необычная и трудная для чтения, а некоторые приемы очень устарели. Я также вижу, что вы по-прежнему копируете только первую строку файла и получаете предупреждающее сообщение. Всегда лучше use warnings и use strict, но мало смысла, если вы игнорируете сообщения, которые они производят. - person Borodin; 22.07.2014