욕심 많은 수량 자와 너무 많이 일치하지 않도록 Regex를 어떻게 고칠 수 있습니까? [복제하다
-
05-07-2019 - |
문제
이 질문은 이미 여기에 답이 있습니다.
다음 줄이 있습니다.
"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;([^;]*);([^;]*);([^;]*);(.*)/