Как я могу удалить текст в начале файла с помощью регулярных выражений? - PullRequest
3 голосов
/ 23 марта 2009

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

Я хочу удалить этот заголовок из всех файлов.

Глядя на файлы, я знаю, что то, что я хочу удалить, заключено между похожими словами.

Так, например, у меня есть:

Foo bar...some text here...
more text
Foo bar...I want to keep everything after this point

Я попробовал эту команду в Perl:

perl -pi -e "s/\A.*?Foo.bar*?Foo.bar//simxg" 00ws110.txt

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

Ответы [ 4 ]

7 голосов
/ 23 марта 2009

По умолчанию ARGV (он же <>, который используется за кулисами -p), читает только одну строку за раз.

Обходные:

  1. Unset $/, который говорит Perl читать весь файл за раз.

    perl -pi -e "BEGIN{undef$/}s/\A.*?Foo.bar*?Foo.bar//simxg" 00ws110.txt
    

    BEGIN необходимо, чтобы этот код выполнялся до того, как будет выполнено первое чтение.

  2. Используйте -0, который устанавливает $/ = "\0".

    perl -pi -0 -e "s/\A.*?Foo.bar*?Foo.bar//simxg" 00ws110.txt
    
  3. Воспользуйтесь оператором триггера .

    perl -ni -e "print unless 1 ... /^Foo.bar/'
    

    Печать будет пропущена, начиная со строки 1 до /^Foo.bar/.

3 голосов
/ 23 марта 2009

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

perl -0777pi.orig -e 's/your regex/your replace/s' file1 file2 file3

Опция -0777 устанавливает perl в режим slurp, поэтому $_ будет удерживать каждый файл целиком каждый раз в цикле. Кроме того, всегда не забывайте устанавливать расширение для резервного копирования. Если вы этого не сделаете, вы можете обнаружить, что вы удалили свои данные случайно и не можете вернуть их. См. perldoc perlrun для получения дополнительной информации.

Учитывая информацию из комментариев, похоже, что вы пытаетесь убрать все раздражающие вещи с передней части Project Gutenberg книги. Если вы понимаете все связанные с этим вопросы авторского права, вы сможете избавиться от основного вопроса, например:

perl -ni.orig -e 'print unless 1 .. /^\*END/' 00ws110.txt

Заголовок Project Gutenberg заканчивается на

*END*THE SMALL PRINT! FOR PUBLIC DOMAIN ETEXTS*Ver.04.29.93*END*

Более безопасное регулярное выражение также будет учитывать *END* в конце строки, но я ленивый.

2 голосов
/ 24 марта 2009

Возможно, я неверно истолковываю то, что вы просите, но мне кажется, что это просто:

perl -ni -e 'print unless 1..($. > 1 && /^Foo bar/)'
0 голосов
/ 23 марта 2009

Вот, пожалуйста! Это заменяет первую строку файла:


use Tie::File;

tie my @array,"Tie::File","path_to_file" or die("can't tie the file");
$array[0] =~s/text_i_want_to_replace/replacement_text/gi;
untie @array;

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

Если вы хотите удалить первые две строки и сохранить что-то от третьей, вы можете сделать что-то вроде этого:


# tie the @array before this
shift @array;
shift @array;
$array[0]=~s/foo bar\.\.\.//gi;
# untie the @array

и это будет именно то, что вам нужно!

...