"1..15,16"과 같은 문자열을 숫자 목록으로 어떻게 확장하려면 어떻게해야합니까?
문제
명령 줄에서 입력을 가져 오는 Perl 응용 프로그램이 있습니다.
application --fields 1-6,8
명령 줄에서 사용자가 요청한대로 필드를 표시해야합니다.
나는 '-'로 '..'를 대체 할 생각을했기 때문에 배열에 저장할 수 있도록 생각했다.
$str = "1..15,16" ;
@arr2 = ( $str ) ;
@arr = ( 1..15,16 ) ;
print "@arr\n" ;
print "@arr2\n" ;
여기서 문제는 @arr가 잘 작동한다는 것입니다 ( @arr2에서는 전체 문자열이 배열 요소로 확장되지 않습니다.
나는 탈출 시퀀스를 사용해 보았지만 운이 없습니다.
이런 식으로 할 수 있습니까?
해결책
이것이 사용자 입력 인 경우 보안 문제가있는 경우 String Eval을 사용하지 마십시오.
사용해보십시오 번호 :: 범위 대신에:
use Number::Range;
$str = "1..15,16" ;
@arr2 = Number::Range->new( $str )->range;
print for @arr2;
유효하지 않은 범위에서 죽지 않으려면 다음을 수행하십시오.
eval { @arr2 = Number::Range->new( $str )->range; 1 } or your_error_handling
또한 있습니다 set :: intspan, 사용 - 대신 .. :
use Set::IntSpan;
$str = "1-15,16";
@arr2 = Set::IntSpan->new( $str )->elements;
그러나 범위는 순서대로 정리되어 있어야하며 겹치지 않는 랩핑이 필요합니다 (누군가가 무엇인지 기억하는 경우 .newsrc 파일에 사용하기 위해 작성되었습니다). 또한 무한한 범위를 허용합니다 (문자열이 시작되는 곳 -숫자 또는 끝 숫자-), 요소 메소드가 켜질 것입니다.
다른 팁
당신은 생각하고 있습니다 @arr2 = eval($str);
입력을 받고 그것을 평가하기 때문에 조심해야합니다. 아마도 당신은해야합니다 @arr2 = eval($str) if ($str =~ m/^[0-9.,]+$/)
추신 : 숫자 :: 범위 패키지에 대해 몰랐지만 엄청난. 번호 :: 범위 ftw.
비트 :: vector :: to_enum의 출력을 다루는 데 같은 문제가있었습니다. 나는 그것을함으로써 그것을 해결했다 :
$range_string =~ s/\b(\d+)-(\d+)\b/expand_range($1,$2)/eg;
그런 다음 내 파일에서도 다음과 같습니다.
sub expand_range
{
return join(",",($_[0] .. $_[1]));
}
따라서 "1,3,5-7,9,12-15"는 "1,3,5,6,7,9,12,13,14,15"로 바뀝니다.
나는 S ///의 두 번째 부분에 그 확장을 넣기 위해 정말로 열심히 노력 했으므로 추가 기능이 필요하지 않지만 작동하지 못했습니다. 나는 숫자 :: 범위가 작동하기 때문에 이것을 좋아합니다.이 방법으로 사소해야 할 일을 위해 다른 모듈을 가져갈 필요가 없습니다.
@arr2 = ( eval $str ) ;
물론 Works는 Eval ()에 매우주의해야합니다.
평가를 사용할 수 있습니다.
$str = "1..15,16" ;
@arr2 = ( eval $str ) ;
@arr = ( 1..15,16 ) ;
print "@arr\n" ;
print "@arr2\n" ;
이것이 사용자 입력 인 경우, 먼저 입력 문자열에서 약간의 검증을 수행하여 Dodgy를 입력하지 않도록 할 것입니다.
분할 사용 :
@parts = split(/\,/, $fields);
print $parts[0];
1-6
print $parts[1];
8
당신은 끈을 포함하는 문자열을 배열에 넣고 요소로 전환 할 수 없습니다 (Perl Black Magic을 사용하는 경우를 제외하고는 여기에 들어 가지 않을 것입니다).
그러나 Regex와 Split은 당신의 친구입니다.