Почему использование является классом символов POSIX в моем regex шаблоне, дающем неожиданные результаты?

Я встретился с некоторым странным поведением Perl: использование класса символов Posix в regexp полностью изменяет порядок сортировки для получивших строк.

Вот моя тестовая программа:

sub namecmp($a,$b) {
  $a=~/([:alpha:]*)/;
  # $a=~/([a-z]*)/;
  $aword= $1;

  $b=~/([:alpha:]*)/;
  # $b=~/([a-z]*)/;
  $bword= $1;
  return $aword cmp $bword;
};

$_= <>;
@names= sort namecmp split;
print join(" ", @names), "\n";

Если Вы изменяетесь на прокомментированный regexp's, использующий [a-z], Вы получаете нормальный, лексикографический порядок сортировки. Однако Posix [: альфа:] класс символов приводит к некоторому порядку сортировки странной задницы, следующим образом:

$test_normal
aaa aab aac aba abb abc aca acb acc baa bab bac bba bbb bbc bca bcb bcc caa cbb
aaa aab aac aba abb abc aca acb acc baa bab bac bba bbb bbc bca bcb bcc caa cbb

$test_posix
aaa aab aac aba abb abc aca acb acc baa bab bac bba bbb bbc bca bcb bcc caa cbb
baa bab bac bba bbb bbc bca bcb bcc caa cbb aba abb abc aca acb acc aab aac aaa

Мое лучшее предположение - то, что класс символов Posix активирует некоторый материал локали, о котором я никогда не слышал и не попросил. Я предполагаю логическую реакцию на "доктора, доктора, причиняет боль, когда я делаю это!", "хорошо, не делайте этого, затем!".

Но, кто-либо может сказать мне, что происходит здесь, и почему? Я использую жемчуг 5.10, но я полагаю, что он также работает под жемчугом 5.8.

7
задан Sinan Ünür 25 February 2010 в 12:43
поделиться

3 ответа

Класс символов [: alpha:] представляет альфа-символы в регулярных выражениях Perl, а квадратные скобки - not означают то, что они обычно делают в регулярных выражениях. Итак, вам нужно:

$a=~/([[:alpha:]]*)/;

Это упоминается в perlre :

Синтаксис символьного класса POSIX

  [: class: ] 
 

также доступен. Обратите внимание, что скобки [ и ] буквальны; они всегда должны использоваться в выражении символьного класса.

# this is correct:
$string =~ /[[:alpha:]]/;

# this is not, and will generate a warning:
$string =~ /[:alpha:]/;
13
ответ дан 6 December 2019 в 06:36
поделиться

То, что вы пишете, ни в коем случае не является Perl. Вы можете избежать наказания, потому что отключили предупреждений .Если бы вы использовали предупреждения, perl сказал бы вам, что

синтаксис POSIX [::] принадлежит классам символов в регулярном выражении; помечено <- ЗДЕСЬ в m / ([: alpha:] <- ЗДЕСЬ *) / в строке 4 j.pl

Синтаксис POSIX [::] принадлежит классам символов в регулярном выражении; отмечены <- ЗДЕСЬ в m / ([: alpha:] <- ЗДЕСЬ *) / в j.pl строке 8.

Представьте себе это!

Итак, perl также сказал бы вам:

Недопустимый символ в прототипе для main :: namecmp: $ a, $ b в строке 3 j.pl

, потому что Perl - это не C. Perl не имеет прототипов функций того типа, который вы, кажется, пытаетесь использовать.

Лучший способ написать точно такую ​​же функциональность на этот раз на Perl:

use warnings; use strict;

sub namecmp {
    my ($aword) = $a =~ /([[:alpha:]]*)/;
    my ($bword) = $b =~ /([[:alpha:]]*)/;
    return $aword cmp $bword;
}

print join(' ', sort namecmp split ' ', scalar <>), "\n";
8
ответ дан 6 December 2019 в 06:36
поделиться

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

test.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich" xmlns:fn="http://java.sun.com/jsp/jstl/functions" xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:fnc="http://eyeprevent.com/fnc">
<a4j:outputPanel id="testing">
<rich:modalPanel id="examinationPanel" autosized="true" width="450" rendered="#{test.condition2}" onhide="stopTimer('false')">
    <f:facet name="header">
        <h:outputText value="View Examination Images" />
    </f:facet>
    <f:facet name="controls">
        <h:panelGroup>
            <a4j:form>
                <a4j:commandLink action="#{test.close}">
                    <h:graphicImage value="/images/modal/close.png" id="hideExaminationPanel" styleClass="hidelink" />
                </a4j:commandLink>
            </a4j:form>
            <rich:componentControl for="examinationPanel" attachTo="hideExaminationPanel" operation="hide" event="onclick" />
        </h:panelGroup>
    </f:facet>
    <a4j:form>
        <h:panelGrid columns="1" id="timeoutText">
            <h:outputText id="remainingtime" value="condition1" rendered="#{test.condition1}" />
            <h:outputText id="timer" value="condition2" rendered="#{test.condition2}" />
        </h:panelGrid>
        <a4j:poll id="poll" interval="5000" enabled="#{test.poll}" reRender="poll,timeoutText" />
    </a4j:form>
</rich:modalPanel>
</a4j:outputPanel>
<h:form>
<a4j:commandLink oncomplete="#{rich:component('examinationPanel')}.show()" reRender="testing">Link</a4j:commandLink>
<a4j:jsFunction name="stopTimer" actionListener="#{test.close}">
    <a4j:actionparam name="param1" assignTo="#{test.poll}" />
</a4j:jsFunction>
</h:form>
</html>

Важно сохранить a4j: jsFunction за пределами modalPanel тэгов.

StartBean.java:

import javax.faces.event.ActionEvent;
import org.apache.log4j.Logger;

public class TestBean {
    private boolean condition1 = false;
    private boolean condition2 = true;
    private boolean poll = true;

    public void close(ActionEvent event) {
        Logger.getLogger("com.eyeprevent").info("here!");
        poll = false;
        condition1 = true;
        condition2 = false;
    }

    public boolean isCondition1() {
        return condition1;
    }

    public void setCondition1(boolean condition1) {
        this.condition1 = condition1;
    }

    public boolean isCondition2() {
        return condition2;
    }

    public void setCondition2(boolean condition2) {
        this.condition2 = condition2;
    }

    public boolean isPoll() {
        return poll;
    }

    public void setPoll(boolean poll) {
        this.poll = poll;
    }
}
-121--4349269-

Класс символов [: alpha:] представляет альфа-символы в регулярных выражениях Perl, но квадратные скобки не означают то, что они обычно делают в регулярных выражениях. Таким образом, необходимо:

$a=~/([[:alpha:]]*)/;

Это упоминается в perlre :

Синтаксис класса символов POSIX

  [: класс:]
Также доступен 

. Обратите внимание, что скобки [ и ] являются буквенными; они всегда должны использоваться в выражении класса символов.

# this is correct:
$string =~ /[[:alpha:]]/;

# this is not, and will generate a warning:
$string =~ /[:alpha:]/;
-121--3783481-

Поскольку Perl не поддерживает классы символов POSIX в этой форме. (Используйте [[: альфа:]] . См. @ ответ Грега )

Поэтому

[:alpha:]

интерпретируется как класс символов, состоящий из символов « a », « h », « l », « p » и «: ».

Теперь для последовательностей, которые ничего не делают, содержат [ahlp:] в начале (из-за * ), например « baa », матч возвращает пустой ряд. Пустая последовательность, конечно, меньше, чем любые другие последовательности, поэтому они будут расположены в начале.

6
ответ дан 6 December 2019 в 06:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: