Удалить текст между двумя кавычками в Perl? - PullRequest
3 голосов
/ 06 марта 2012

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

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

Я использовал что-то вроде этого:

perl -p -i.bak -e s/bar/foo/g bar.xml

сначала найти и заменить то, что сработало. Тогда я пошел к:

perl -p -i.bak -e s/..\/..\/bar\//g bar.xml

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

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

Ответы [ 3 ]

5 голосов
/ 06 марта 2012
s/"[^"]*foo[^"]*"//g

работает, если между фактическими кавычками нет экранированных кавычек и если вы хотите удалить строку в кавычках, содержащую foo:

"      # Match a quote
[^"]*  # Match any number of characters except quotes
foo    # Match foo
[^"]*  # Match any number of characters except quotes
"      # Match another quote
2 голосов
/ 08 марта 2012

Некоторые люди спрашивали о кавычках.Здесь есть несколько хитростей.Вы хотите игнорировать экранированные кавычки, такие как \", но не символы кавычек, которые имеют экранированные экранированные символы, например \\".Чтобы игнорировать первое, я использую негативный взгляд сзади.Чтобы не игнорировать второе, я временно изменяю все \\ на ?.Если у вас есть ? в ваших данных, выберите что-то еще.

use v5.14;
use utf8;
use charnames qw(:full);

my $regex = qr/
    (?<!\\) "  # a quote not preceded by a \ escape
    (.*?)      # anything, non greedily
    (?<!\\) "  # a quote not preceded by a \ escape
    /x;

while( <DATA> ) {
    # encode the escaped escapes for now
    s/(?:\\){2}/\N{SMILING CAT FACE WITH OPEN MOUTH}/g;
    print "$.: ", $_;

    while( m/$regex/g ) {
        my $match = $1;
        # decode the escaped escapes
        $match =~ s/\N{SMILING CAT FACE WITH OPEN MOUTH}/\\\\/g;
        say "\tfound → $match";
        }
    }

__DATA__
"One group" and "another group"
This has "words between quotes" and words outside
This line has "an \" escaped quote" and other stuff
Start with \" then "quoted" and "quoted again"
Start with \" then "quoted \" with escape" and \" and "quoted again"
Start with \" then "quoted \\" with escape"
Start with \" then \\\\"quoted \\" with escape\\"

Вывод:

1: "One group" and "another group"
    found → One group
    found → another group
2: This has "words between quotes" and words outside
    found → words between quotes
3: This line has "an \" escaped quote" and other stuff
    found → an \" escaped quote
4: Start with \" then "quoted" and "quoted again"
    found → quoted
    found → quoted again
5: Start with \" then "quoted \" with escape" and \" and "quoted again"
    found → quoted \" with escape
    found → quoted again
6: Start with \" then "quoted ?" with escape"
    found → quoted \\
7: Start with \" then ??"quoted ?" with escape?"
    found → quoted \\
0 голосов
/ 21 февраля 2016

Вы вводите говорит, что файл .xml - так что я собираюсь сказать, что я обычно делаю.

Используйте синтаксический анализатор XML - мне нравится XML::Twig, потому что я думаю, что сначала легче разобраться с ним. XML::LibXML тоже хорошо.

Теперь, основываясь на вопросе, который вы задаете - это , как , вы пытаетесь переписать путь к файлу в атрибуте XML.

Итак:

#!/usr/bin/env perl/

use strict;
use warnings;

use XML::Twig;

#my $twig = XML::Twig -> parsefile ( 'test.xml');
my $twig = XML::Twig -> parse ( \*DATA );

foreach my $element ( $twig -> get_xpath('element[@path]') ) {
   my $path_att = $element -> att('path');
   $path_att =~ s,/\.\./\.\./bar/,,g;
   $element -> set_att('path', $path_att);
}

$twig -> set_pretty_print('indented_a');
$twig -> print;
__DATA__
<root>
   <element name="test" path="/path/to/dir/../../bar/some_dir">
   </element>
   <element name="test2" nopath="here" />
   <element path="/some_path">content</element>
</root>

XML::Twig также весьма полезно поддерживает parsefile_inplace для работы в «стиле sed» для изменения файла. Выше приведена иллюстрация концепции с некоторым примером XML - с более ясным примером того, что вы пытаетесь сделать, я смогу улучшить его.

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