문제
여기에 문제가에 달렸다.저는 속성 문의 양식
"x=1 and y=abc and z=c4g and ..."
몇 가지 특성이 있는 숫자 값,일부는 알파 값은 일부가 혼합된,일부입니다.
모든 문자열 정 하"x=someval and y=anotherval
"처음에는,그러나 몇 가지 하지 않습니다.저는 세 가지를 내가해야 할 수 있습니다.
- 유효성을 검증할 문자열을 특정들
x
고y
. - 실제로 구문 분석에 대한 값
x
고y
. - 나머지의 문자열입니다.
주어진 예 맨 위에,이것은 다음과 같은 변수:
$x = 1;
$y = "abc";
$remainder = "z=c4g and ..."
나의 질문은:이 있(합리적으로)간단한 방법으로 이러한 구문 분석 고 검증으로 하나의 정규 표현식?즉:
if ($str =~ /someexpression/)
{
$x = $1;
$y = $2;
$remainder = $3;
}
참고하는 문자열 수 있습으로 구성 만 x
고 y
특성이 있습니다.이것은 유효한 문자열입니다.
나는 나의 솔루션에 대한 답변으로,그러나 그것을 만나지 않 내 single-regex 니다.
해결책
나는 최고의에서는 정기적인 표현,하지만 이것은 아주 가까이 무엇을 찾고 있:
/x=(.+) and y=([^ ]+)( and (.*))?/
를 제외하고 사용할$1,$2$4.에서 사용:
my @strs = ("x=1 and y=abc and z=c4g and w=v4l",
"x=yes and y=no",
"z=nox and w=noy");
foreach (@strs) {
if ($_ =~ /x=(.+) and y=([^ ]+)( and (.*))?/) {
$x = $1;
$y = $2;
$remainder = $4;
print "x: $x; y: $y; remainder: $remainder\n";
} else {
print "Failed.\n";
}
}
출력:
x: 1; y: abc; remainder: z=c4g and w=v4l
x: yes; y: no; remainder:
Failed.
이 과정의 목적으로 충분의 오류를 검사하며,검사를 하나라도 통과하지 알아에 대한 모든 것을 입력하지만,이 작동하는 것 같다.
다른 팁
고 가정하고 당신은 또한 당신을 위해 무언가 하고 싶은 다른 이름=값 쌍으로 이것은 어떻게 할 지에 대해서 그것은(를 사용하여 Perl 버전 5.10):
use 5.10.0;
use strict;
use warnings;
my %hash;
while(
$string =~ m{
(?: ^ | \G ) # start of string or previous match
\s*
(?<key> \w+ ) # word characters
=
(?<value> \S+ ) # non spaces
\s* # get to the start of the next match
(?: and )?
}xgi
){
$hash{$+{key}} = $+{value};
}
# to make sure that x & y exist
die unless exists $hash{x} and exists $hash{y};
이전 Perls(적어도 Perl5.6);
use strict;
use warnings;
my %hash;
while(
$string =~ m{
(?: ^ | \G ) # start of string or previous match
\s*
( \w+ ) = ( \S+ )
\s* # get to the start of the next match
(?: and )?
}xgi
){
$hash{$1} = $2;
}
# to make sure that x & y exist
die unless exists $hash{x} and exists $hash{y};
이러한의 혜택을 추가 작업을 계속하고 업무를 수행해야 하는 경우에는 더 많은 데이터입니다.
으로 매우 간단한 수정하 러드의 버전
/^x=(.+) and y=([^ ]+)(?: and (.*))?/
를 사용할 수 있는$1,$2$3(?:게 비캡처 group),그리고 것을 보장하는 문자열로 시작하"x="보다는 허용"not_x="치
는 경우에 당신은 더 나은 지식을 가지고 무엇 x 와 y 값이 될 것입니다,이해하는 데 사용될 조 regex 더:
my @strs = ("x=1 and y=abc and z=c4g and w=v4l",
"x=yes and y=no",
"z=nox and w=noy",
"not-x=nox and y=present",
"x=yes and w='there is no and y=something arg here'");
foreach (@strs) {
if ($_ =~ /^x=(.+) and y=([^ ]+)(?: and (.*))?/) {
$x = $1;
$y = $2;
$remainder = $3;
print "x: {$x}; y: {$y}; remainder: {$remainder}\n";
} else {
print "$_ Failed.\n";
}
}
출력:
x: {1}; y: {abc}; remainder: {z=c4g and w=v4l}
x: {yes}; y: {no}; remainder: {}
z=nox and w=noy Failed.
not-x=nox and y=present Failed.
x: {yes and w='there is no}; y: {something}; remainder: {}
참고 누락된 부분의 마지막 테스트 때문에 현재 버전의 테스트 요구하는 공백이 없는 경우,x 테스트는 동일한 제한이 있는 문자열 것에 실패했습니다.
러드와 Cebjyre 받고 있는 대부분의 방법이 있지만 그들은 모두 특정 문제점:
러드는 제안:
/x=(.+) y=([^]+)(고(.*))?/
Cebjyre 수정한다:
/^x=(.+) y=([^ ]+)(?:고(.*))?/
두번째 버전은 더 나은 것이기 때문에 혼동하지"not_x=foo""x=foo"하지만 받아들이는 것 같은"x="foo"z=바 y=baz"설정 1 달러="foo z=바하는"바람직하지 않습니다.
이것은 아마도 당신이 찾고있는 무엇:
/^x=(\w+)y=(\w+)(?:고(.*))?/
이것을 허용하지 않도 사 x=y=옵션,장소 및할 수 있고 선택 사항"고..."는 것에서$3
여기에 기본적으로 무엇을 했는지 이를 해결하기:
($x_str, $y_str, $remainder) = split(/ and /, $str, 3);
if ($x_str !~ /x=(.*)/)
{
# error
}
$x = $1;
if ($y_str !~ /y=(.*)/)
{
# error
}
$y = $1;
나는 생략 몇 가지 추가 유효성 검사 오류를 처리합니다.이 기술은 일이지만,그것은 없으로 간결한 또는 예쁜 나가 좋아했을 것이다.내가 누군가를 희망하는 것입니다 더 나은 제안한다.