Perl регулярные выражения в системных вызовах - PullRequest
1 голос
/ 05 апреля 2011

Следующая строка Perl работает так, как я ожидаю; он удаляет мой файл начальных и конечных пробелов и заменяет промежуточные пробелы одной вкладкой:

$ perl -pi -le 's/^\s+//; s/\s+$//; s#\s+#\t#g;' file

Что меня смущает, так это то, что я не могу заставить это работать через system звонок из моего кода Perl:

system "perl -pi -le 's/^\s+//; s/\s+\$//; s#\s+#\t#g;' file";  # '$' backslashed

В чем здесь проблема?

Ответы [ 8 ]

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

Нет необходимости запускать другой процесс для -i, но в целом вам следует локализовать некоторые глобальные переменные:

sub do_stuff {
  my $file = shift;
  local ($_, $., $ARGV, *ARGV);
  local ( $^I, @ARGV ) = ( '.bak', $file );

  while ( <> ) {
    s/..../..../;
    print;
  }
}
2 голосов
/ 05 апреля 2011
say "perl -pi -le 's/^\s+//; s/\s+\$//; s#\s+#\t#g;' file";

производит

Unrecognized escape \s passed through at -e line 1.
Unrecognized escape \s passed through at -e line 1.
Unrecognized escape \s passed through at -e line 1.
perl -pi -le 's/^s+//; s/s+$//; s#s+#   #g;' file

Вы хотите

system("perl -pi -le 's/^\\s+//; s/\\s+\$//; s#\\s+#\\t#g;' file");

Собственно, зачем вообще вызывать оболочку?

system('perl', '-i', '-ple' 's/^\\s+//; s/\\s+$//; s#\\s+#\\t#g;', 'file');
1 голос
/ 06 апреля 2011

runrig показал, что вам не нужно создавать подпроцесс только для использования -i. Внутреннее использование -i немного странно, поэтому есть две более чистые альтернативы. Первый - использовать Tie :: File , что довольно просто.

Другой способ - записать во временный файл, используя File :: Temp , что по сути то, что делает -i.

my $tmp = File::Temp->new;
open my $fh, "<", $file or die "Can't open $file: $!";

while(<$fh>) {
    s/.../.../;
    print $tmp $_;
}

my $tmpfile = $tmp->filename;
rename $tmpfile, $file or die "Can't rename $tmpfile to $file: $!";
1 голос
/ 05 апреля 2011

Вы забываете, что обратные слеши сначала анализируются как строка в двойных кавычках Perl, а затем как команда оболочки.

Эквивалент командной строки:

perl -pi -le 's/^\s+//; s/\s+$//; s#\s+#\t#g;' file

в скрипте Perl -

system "perl -pi -le 's/^\\s+//; s/\\s+\$//; s#\\s+#\\t#g;' file"

Хотя глупо запускать еще одну копию Perl только для этого. Вам, вероятно, лучше использовать еще несколько строк кода и делать это в том же процессе.

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

Это как раз та ситуация, для которой Ларри дал нам символы альтернативной кавычки.Мы хотели бы использовать одинарные кавычки для аргумента system (), чтобы нам не приходилось выяснять, что требует обратной косой черты, но нам также нужны одинарные кавычки в самой строке в кавычках.Итак, альтернативные символы кавычек для спасения!

system q(perl -p -le 's/^\s+//; s/\s+$//; s#\s+#\t#g;' file);

Теперь вы можете копировать / вставлять то, что работает в командной строке, прямо в исходный код Perl.

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

для Linux попробуйте

system q(perl -pi -le 's/^\s+//; s/\s+$//; s#\s+#\t#g;' file); # comments here

для M $ windows:

system q(perl -pi -le "s/^\s+//; s/\s+$//; s#\s+#\t#g;" file); # comments here
0 голосов
/ 05 апреля 2011

Двойные кавычки интерпретируют все.

try:

system "perl -pi -le 's/^\\s+//; s/\\s+\$//; s\#\\s+\#\\t\#g;' file";
0 голосов
/ 05 апреля 2011

Внутри двойных кавычек ' имеет нет функциональное значение.Ваша строка будет отредактирована Perl.Мои тесты показывают, что вы теряете выражения \s.Это также интерполирует '\t'.Вкладка - хотя это может быть и не такой большой проблемой.

Вот Data::Dumper Взятие

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...