욕심 많은 수량 자와 너무 많이 일치하지 않도록 Regex를 어떻게 고칠 수 있습니까? [복제하다

StackOverflow https://stackoverflow.com/questions/255815

문제

이 질문은 이미 여기에 답이 있습니다.

다음 줄이 있습니다.

"14:48 say;0ed673079715c343281355c2a1fde843;2;laka;hello ;)"

간단한 regexp를 사용하여 이것을 구문 분석합니다.

if($line =~ /(\d+:\d+)\ssay;(.*);(.*);(.*);(.*)/) {
    my($ts, $hash, $pid, $handle, $quote) = ($1, $2, $3, $4, $5);
}

하지만 ; 결국 물건을 엉망으로 만들고 왜 그런지 모르겠습니다. 욕심 많은 운영자가 "모든 것"을 처리해서는 안됩니까?

도움이 되었습니까?

해결책

욕심 많은 운영자는 가능한 한 많은 것들을 잡고 문자열과 일치 시키려고합니다. 일어나는 일은 첫 번째 ( "Say"이후)가 "0ed673079715c34328135c2c2a1fde843; 2", 두 번째는 "laka"를 취하고, 세 번째는 "hello"를 발견하고 네 번째는 괄호와 일치합니다.

당신이해야 할 일은 마지막이 아닌 사람을 제외한 모든 것을 만드는 것입니다. 그래서 그들은 가능한 한 적게 잡고 여전히 끈과 일치합니다.

(\d+:\d+)\ssay;(.*?);(.*?);(.*?);(.*)

다른 팁

(\d+:\d+)\ssay;([^;]*);([^;]*);([^;]*);(.*)

더 잘 작동해야합니다

정수가 쉽게 할 수 있지만, 그것이 가장 간단한 접근법인지 확실하지 않습니다. 아마도 가장 짧은 일이지만 실제로는 가장 유지 가능하게 만드는 것은 아닙니다.

대신, 나는 다음과 같은 것을 제안합니다.

$x="14:48 say;0ed673079715c343281355c2a1fde843;2;laka;hello ;)";

if (($ts,$rest) = $x =~ /(\d+:\d+)\s+(.*)/)
{
    my($command,$hash,$pid,$handle,$quote) = split /;/, $rest, 5;
    print join ",", map { "[$_]" } $ts,$command,$hash,$pid,$handle,$quote
}

결과가 발생합니다.

[14:48],[say],[0ed673079715c343281355c2a1fde843],[2],[laka],[hello ;)]

나는 이것이 조금 더 읽기 쉽다고 생각합니다. 뿐만 아니라, 인간이 펜과 종이로 같은 일을 시도한다면 어떻게 할 것인지에 더 가깝기 때문에 디버깅하고 유지하는 것이 더 쉽다고 생각합니다. 문자열을 덩어리로 나누어서 더 쉽게 구문 분석 할 수 있습니다. 컴퓨터가 당신이 할 일을 정확하게 수행하도록하십시오. 수정을 할 때가되면, 나는 이것이 더 나아질 것이라고 생각합니다. ymmv.

처음 3을 만들어보십시오 (.*) Ungreedy (.*?)

세미콜론-지정 목록의 값에 세미콜론 자체가 포함될 수없는 경우, 철자를 사용하여 가장 효율적이고 간단한 정규 표현을 얻을 수 있습니다. 특정 값이 16 진 문자 문자열 일 수 있다면 철자를 쓸 수 있습니다. 게 픽이 주제 문자열과 일치하지 않으면 게으른 욕구를 사용하는 솔루션은 항상 쓸모없는 역 추적으로 이어집니다.

(\d+:\d+)\ssay;([a-f0-9]+);(\d+);(\w+);([^;\r\n]+)

물음표를 추가하여 * 비-그 리디를 만들 수 있습니다.

$line =~ /(\d+:\d+)\ssay;(.*?);(.*?);(.*?);(.*)/

또는 마지막 부분을 제외한 각 부분의 세미콜론을 제외한 모든 것을 일치시킬 수 있습니다.

$line =~ /(\d+:\d+)\ssay;([^;]*);([^;]*);([^;]*);(.*)/
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top