Регулярное выражение Perl в тибетском сценарии - PullRequest
1 голос
/ 09 октября 2009

Я пытаюсь удалить / удалить второй последний символ тибетского сценария, как показано ниже (символы в следующем примере написаны на английском языке):

$char = "ti.be.tan.|";           

Итак, я хочу удалить "второй последний" символ "." Я пробовал следующим образом, имея немного знаний о RE:

$char =~ s/.|$/|/g;
$char =~ s/[.|]$/|/g;
$char = tr/.|//d;       # and later add |.

Что я делаю не так?

Ответы [ 4 ]

8 голосов
/ 09 октября 2009

Прежде чем я скажу вам, что вам нужно делать правильно, давайте посмотрим, что вы делаете неправильно:

$char =~ s/.|$/|/g;

Проблема здесь в том, что и ., и | являются метасимволами в регулярных выражениях. | означает «или», то есть вы говорите «соответствует . или $». Вы правильно знаете, что $ означает конец строки, но . означает «любой один символ». Таким образом, он немедленно соответствует одному символу и продолжает немедленно соответствовать одному символу, каждый раз меняя этот символ на | (метасимволы не применяются во второй половине выражения s///), затем он соответствует концу строки и добавляет | там. Или что-то типа того. По сути, не то, что вы хотите, чтобы произошло.

$char =~ s/[.|]$/|/g;

Ну, внутри [] s, . и | перестают быть метасимволами, но [] означает «один из них», так что это регулярное выражение ищет символ перед концом строки, и если это либо |, либо ., оно меняется на |. Опять же, не то, что вы хотите, чтобы это произошло.

$char = tr/.|//d;       # and later add |.

tr не тот инструмент для этой работы. Это приведет к удалению всех символов . и | в вашей строке. Предположим, вы используете не оператор сопоставления регулярных выражений * 1032, а оператор присваивания =. Определенно не то, что вы хотите, чтобы произошло.

То, что вы хотите, это:

$char =~ s/\.\|$/|/;

Мы избежали как ., так и | с \, поэтому Perl знает, что «символ после \ является буквенным символом без специального значения *» и соответствует литералу .| в конце вашей строки и заменяет его просто |.

Тем не менее, звучит так, будто вы новичок в регулярных выражениях. Я большой поклонник perldoc perlretut, который, я думаю, является одним из лучших (если не лучших) введений в регулярные выражения в Perl. Вы должны действительно прочитать это - регулярные выражения - мощный инструмент в руках тех, кто их знает, и сильная головная боль для тех, кто не знает.

3 голосов
/ 09 октября 2009

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

Вот оно:

$char =~ s/(.)(.)$/\2/g;

По сути, Perl (на самом деле RegEx) отобразит все между '(' и ')' в группы. Что вы можете манипулировать этой группой позже. Из этого кода гурфы.

$char =~ s/(.)(.)$/\2/g;
#          ^-^^-^  ^^
#  Capture G1 G2   ++-- Then replace it with only group 2

Таким образом, в этом случае Perl идет от первого символа, поскольку он не соответствует ни одному, он отпускает (не заменяет), когда он находит совпадение, он заменяет совпадение на то, что вы указали (в данном случае это группа # 2).

Надеюсь, это поможет.

1 голос
/ 09 октября 2009

Вы также можете использовать substr в качестве lvalue в этой ситуации:

$char = "ti.be.tan.|";
substr($char,-2,1) = "";
print $char;               # ===>  ti.be.tan|
0 голосов
/ 11 октября 2009

Существует также метод, использующий положительное утверждение для удаления второго последнего символа.

$char ~= s/.(?:.$)//;

Что по сути означает замену любого символа "", за которым сразу следует один символ и конец строки.

Если второй последний символ всегда является определенным символом, вы можете заменить первый. Не забудьте экранировать метасимволы RE () [] /.*?

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