Странное поведение в регулярном выражении Perl с глобальной заменой - PullRequest
17 голосов
/ 10 мая 2011

Может ли кто-нибудь объяснить мне, почему вывод этого маленького Perl-скрипта "foofoo" (а не "foo")?

#!/usr/bin/perl -w 
my $var="a";
$var=~s/.*/foo/g;
print $var."\n";

Без опции g она работает так, как я и хотел бы, но почему глобальная опция сопоставляет шаблон дважды?

В bash вывод «foo», как и ожидалось

echo "a"|sed -e "s/.*/foo/g" 

Любое объяснение будет оценено.

Ответы [ 4 ]

12 голосов
/ 10 мая 2011

Сначала .* соответствует a, затем соответствует пустой строке после a. Может быть, вы хотите .+?

8 голосов
/ 10 мая 2011

Будет веселее, если вы попробуете

$var=~s/.*?/foo/g;

Вы получите

foofoofoo

? модификатор соответствует 1 или 0 раз. Если вы удалите г, вы получите

fooa

потому что он заменит только пустую строку, первую найденную. Я люблю Perl.

6 голосов
/ 10 мая 2011

Если вы добавите re в свой код:

use re 'debug';

, вы увидите, что регулярное выражение успешно совпадает дважды:

Compiling REx `.*'
size 3 Got 28 bytes for offset annotations.
first at 2
   1: STAR(3)
   2:   REG_ANY(0)
   3: END(0)
anchored(MBOL) implicit minlen 0
Offsets: [3]
        2[1] 1[1] 3[0]
Matching REx ".*" against "a"
  Setting an EVAL scope, savestack=5
   0 <> <a>               |  1:  STAR
                           REG_ANY can match 1 times out of 2147483647...
  Setting an EVAL scope, savestack=5
   1 <a> <>               |  3:    END
Match successful!
Matching REx ".*" against ""
  Setting an EVAL scope, savestack=7
   1 <a> <>               |  1:  STAR
                           REG_ANY can match 0 times out of 2147483647...
  Setting an EVAL scope, savestack=7
   1 <a> <>               |  3:    END
Match successful!
Matching REx ".*" against ""
  Setting an EVAL scope, savestack=7
   1 <a> <>               |  1:  STAR
                           REG_ANY can match 0 times out of 2147483647...
  Setting an EVAL scope, savestack=7
   1 <a> <>               |  3:    END
Match possible, but length=0 is smaller than requested=1, failing!
                            failed...
Match failed
foofoo
Freeing REx: `".*"'
6 голосов
/ 10 мая 2011

Это потому, что вы используете .* вместо .+

Модификатор * указывает механизму регулярных выражений сопоставить (и заменить в вашем примере) строку «a», а затем ноль-длина строки (и также замените ее).

Вы можете проверить это с помощью этого регулярного выражения в своем примере кода:

$var=~s/(.*)/<$1>/g;

Затем вы увидите этот вывод:

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