Почему мой Perl-скрипт удаляет символы из файла? - PullRequest
1 голос
/ 21 ноября 2008

У меня есть проблема со скриптом Perl. Он изменяет содержимое файла, затем снова открывает его для записи, и в процессе некоторые символы теряются. Все слова, начинающиеся с «%», удаляются из файла. Это довольно раздражает, потому что выражения% являются переменными заполнителями для диалоговых окон.

У вас есть идеи, почему? Исходный файл представляет собой XML с кодировкой по умолчанию

Вот код:

undef $/;
open F, $file or die "cannot open file $file\n";
my $content = <F>;                                           
close F;                                                     

$content =~s{status=["'][\w ]*["']\s*}{}gi;

printf $content;

open F, ">$file" or die "cannot reopen $file\n";             
printf F $content;                                           
close F or die "cannot close file $file\n";

Ответы [ 5 ]

26 голосов
/ 21 ноября 2008

Вы используете printf там, и он думает, что его первый аргумент является строкой формата. Подробнее см. Документацию printf . Когда я сталкиваюсь с такой проблемой, я всегда проверяю, правильно ли я использую функции. :)

Вы, вероятно, хотите просто print :

 print FILE $content;

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

open my($in),  "<", $file       or die "cannot open file $file\n";
open my($out), ">", "$file.bak" or die "cannot open file $file.bak\n";

while( <$in> )
    {
    s{status=["'][\w ]*["']\s*}{}gi;
    print $out;
    }

rename "$file.bak", $file or die "Could not rename file\n";

Это также сводится к этой программе командной строки:

% perl -pi.bak -e 's{status=["\']\\w ]*["\']\\s*}{}g' file
4 голосов
/ 21 ноября 2008

Er. Вы используете printf.

printf интерпретирует "%" как нечто особенное.

используйте вместо этого «печать».

Если вам нужно использовать printf, используйте

printf "%s", $content;

Важное примечание:

PrintF расшифровывается как Print Format, как и в C.

fprintf - это эквивилент в C для File IO.

Perl не является C.

И даже в С, размещение вашего контента в качестве параметра 1 дает вам шанс по соображениям безопасности.

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

Это потому, что вы использовали printf вместо print, и вы знаете, что printf не печатает "%" (потому что может показаться, что вы забыли ввести символ формата, такой как% s,% f и т. Д.), Если вы не упомянули явно "% %». : -)

0 голосов
/ 23 ноября 2008

Если вам нужно решение, которое знает XML-природу документов (то есть удаляет только атрибуты статуса, а не совпадает с текстовым содержимым), вы также можете использовать XML :: PYX :

$ pyx doc.xml | perl -ne'print unless /^Astatus/' | pyxw
0 голосов
/ 21 ноября 2008

Или даже

perl -i bak -pe 's{status=["\'][\w ]*["\']\s*}{}gi;' yourfiles

-e говорит "есть код для запуска"

-i bak говорит "переименуйте старый файл в what.bak"

-p добавляет цикл чтения-печати вокруг кода -e

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

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