Perl의 Glob에는 제한이 있습니까?


9

5 개의 예상되는 반환 문자열을 실행 중입니다.

while (glob '{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}'x5) {
  print "$_\n";
}

그러나 4 문자 만 반환합니다.

anbc
anbd
anbe
anbf
anbg
...

그러나 목록의 문자 수를 줄이면 :

while (glob '{a,b,c,d,e,f,g,h,i,j,k,l,m}'x5) {
  print "$_\n";
}

올바르게 반환됩니다.

aamid
aamie
aamif
aamig
aamih
...

누군가 내가 여기서 누락 된 것을 말해 줄 수 있습니까, 어떤 종류의 한계가 있습니까? 아니면이 주위에 방법이 있습니까?

그것은 어떤 차이가있는 경우, 그것은 모두 같은 결과를 반환 perl 5.26하고perl 5.28


이전 : stackoverflow.com/a/58852104 stackoverflow.com/a/58853045 glob 기능을 남용하는 대신 반복자를 제공하는 모듈을 사용하십시오. p3rl.org/Algorithm::Combinatorics p3rl.org/Algorithm::Loops
daxim

감사합니다 @daxim. 문제는 현재 모든 종류의 모듈을로드하는 데 어려움을 겪고 있다는 것입니다 .Win32 :: Console에 대해 불평하는 cpan 문제가 있지만 perl 5.28에서 ppm을 사용할 수 없으므로 cpan에 대한 모듈을로드하여 불평을 중지 할 수 있습니다.
Gerry

감사합니다 @zdim은 모든 시간과 노력에 감사드립니다.
Gerry

방금 깨달았습니다 ...이 셔플 (무작위 화)을 원하십니까, 아니면 전체 목록을 원하십니까?
zdim

@zdim은 전체 목록입니다. :)
Gerry

답변:


6

모든 것은 약간의 제한이 있습니다.

다음은 반복적으로 수행 할 수있는 순수한 Perl 모듈입니다. 전체 목록을 한 번에 생성하지 않으며 즉시 결과를 얻기 시작합니다.

use v5.10;

use Set::CrossProduct;

my $set = Set::CrossProduct->new( [ ([ 'a'..'z' ]) x 5 ] );

while( my $item = $set->get ) {
    say join '', @$item
    }

당신은 내가 지금 얼마나 행복한 지 이해하지 못합니다. 대단히 감사합니다 !!
Gerry

3
알고리즘 :: 루프의이 NestedLoops또한 사용될 수있다 : use Algorithm::Loops qw( NestedLoops ); NestedLoops([ ([ 'a'..'z' ]) x 5 ], sub { say join '', @_ } ); (방공호에 의해 이전 질문에 대한 답변들이 메모리 부족한다면 그들은이를 사용할 수 있습니다 언급 ...)
이케 가미

8

glob번째는 가능한 모든 파일 이름 확장명을 작성하므로, 주어진 쉘 스타일 glob / pattern에서 전체 목록 을 먼저 생성합니다 . 스칼라 컨텍스트에서 사용되는 경우에만 반복됩니다. 그것이 반복자를 소진하지 않고 탈출하는 것이 너무 어려운 이유입니다. 이 게시물을 참조하십시오 .

첫 번째 예에서는 26 5 개의 문자열 ( 11_881_376)이며 각각 5 자입니다. 따라서 ~ 1,200 만 개의 문자열 목록과 총 순이익이 56Mb를 초과합니다 ... 스칼라의 오버 헤드와 최소 12 바이트 정도라고 생각합니다. 따라서 100Mb의 순서로 최소한 하나의 목록에 있습니다.

나는 Perl (정규식이 아닌)의 길이에 대한 공식적인 제한을 알고 glob있지 않지만 내부적으로 그리고 문서화되지 않은 한계가 있어야합니다. 어쩌면 일부 버퍼가 내부 어딘가에서 오버런됩니까? 조금 과도합니다.

이 문제를 해결하는 방법 glob은 마술을 장면 뒤에서 굴리는 대신 5 문자 문자열 목록을 반복적으로 생성하는 것입니다 . 그렇다면 절대 문제가 없어야합니다.

그러나 그 경우에도 모든 것이 편안함을 위해 조금 큽니다. 한 번에 하나의 목록 요소 ( "반복자")를 생성하고 제공하는 알고리즘을 작성하고 작업하는 것이 좋습니다.

그것을 할 수있는 좋은 라이브러리가 있으며 그중 일부는 Algorithm :: Loops : 이 문제에 대한 이전 게시물 (및 주석), Algorithm :: Combinatorics (동일한 주석), Set::CrossProduct다른 대답에서 권장됩니다 여기 ...

또한 이것이 현명하게 사용되는 반면 glob라이브러리는 파일로 작업하기위한 것입니다. 원칙적으로 그것을 잘못 사용하는 것 외에도 유효한 항목에 대해 (~ 1,200 만) 이름을 검사 할 것이라고 생각합니다 ! ( 이 페이지를 참조 하십시오 .) 불필요한 디스크 작업이 많이 있습니다. (그리고 당신이 좋아 "globs의"를 사용한다면 *또는 ?일부 시스템에서 당신이 조용히 다른 결과를 얻을 것, 그래서 실제로 파일이있는 경우에만 문자열 목록을 반환합니다.)


 5 문자 스칼라 크기로 56 바이트를 얻습니다. 익명의 스칼라보다 조금 더 많은 변수가 필요하지만, 길이가 4 인 문자열이있는 테스트 프로그램에서 실제 총 크기는 순진하게 계산 된 것보다 큰 크기입니다. 따라서 실제 작업은 한 번의 작업으로 1Gb 정도일 수 있습니다.

업데이트   동일한 glob접근 방식을 사용하여 5 자 길이의 문자열 목록을 생성하는 간단한 테스트 프로그램은 서버급 컴퓨터에서 15 분 동안 실행되었으며 725MB의 메모리를 사용했습니다.

이 서버에서 올바른 수의 실제 5 자 길이의 문자열을 생성했습니다.


@Gerry 첫째, 나는 문제가 한계에 있는지 확신하지 못한다. 찾아보기 ... 아마도 목록을 먼저 반복적으로 생성하고 (한 번에 모두는 아님) 적절한 배열에 저장합니까? 5 문자열의 "소수"인 한도 근처에는 확실히 도달 할 수 없습니다. (또한 진단 적입니다. --- 작동하면 실제로 내부 한계입니다.)
zdim

@Gerry 모듈이 필요하지 않습니다 --- (5 개의 문자열로 된 목록)을 배열을 사용하여 한 번에 하나씩 묶는 대신 배열로 glob만듭니다. (단순하고 다른 알고리즘이 필요할 것입니다. 아마도 이전 질문에 게시 한 내용 일 것입니다. 좋은 디버깅입니다. 문제없이 목록을 얻을 수 있다면 여기에 한계가 있다는 것을 알 수 있습니다.) 내가 게시물에 도착하는 ...
zdim

@Gerry time perl -MDevel::Size=total_size -wE'$chs = join ",", "a".."z"; @items = glob "{$chs}"x5; say STDERR "Total memory: ", total_size(\@items)/(1024**2), " Mb"... 그리고 확인하겠습니다 ... 이제 30 초 만에 캐시가 어떻게 작동하는지 확인할 수 있습니다. 또한 RSS가 진행되는 동안 외부 도구로 RSS를 확인했습니다.
zdim

@Gerry v5.29.2에서 동일한 동작 (~ 600Mb) ... 여전히이 서버에서 해당 캐시를 타고 있습니다 :))))
zdim

@Gerry v5.16-28 분 (진행 중 과소 평가됨) 및 750Mb의 다른 서버 클래스 시스템의 결과입니다. 이제 5.29.2에서 다시 ~ 600Mb로 다시 전송됩니다. 올바른 문자열과 올바른 수 (정확히 26**5)
zdim
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.