전역 일치에서 무작위 항목 반환

전역 일치에서 무작위 항목 반환

와 함께글로벌 예선zsh파일 이름 와일드카드 패턴 일치 결과는 여러 가지 방법으로 정렬 될 수 있습니다 . 예를 들어, 이 패턴은 *(om)수정 타임스탬프를 기준으로 현재 디렉터리에서 숨겨지지 않은 모든 이름과 일치합니다.

하지만 가끔은 방법이 있었으면 좋겠어무작위화정렬(예: 파일의 무작위 샘플 가져오기) 내가 아는 한, 이 작업을 직접적으로 수행하는 한정자는 없습니다.

zsh질문: 파일 이름 글로빙 패턴에서 임의의 경로 이름 목록을 얻는 방법은 무엇입니까 ?

답변1

임의 정렬 키(글로벌 예선 oe)::

*(Noe\''REPLY=$RANDOM,$RANDOM'\')

설명하다:

  • oe그 뒤에는 단일 문자 구분 기호, 코드 및 다른 구분 기호가 옵니다. 코드 블록에는 구분 기호가 포함될 수 없습니다. 전역 한정자 자체를 구문 분석할 때 특수 문자가 구문 분석되지 않도록 특수 문자를 이스케이프해야 합니다.
  • 나는 '구분 기호로 사용하고(이스케이프가 필요하므로 백슬래시 사용) '존재할 수 있는 특수 문자를 보호하기 위해 코드를 래핑합니다. 이렇게 하면 '.
  • 일치하는 각 파일 이름에 대해 코드 블록이 차례로 실행됩니다.
  • REPLY처음에는 파일 이름으로 설정되고 코드에 의해 설정된 모든 것이 REPLY정렬 키로 사용됩니다.

$n요소를 무작위로 샘플링하려면 […]한정자를 추가하세요.

*(Noe\''REPLY=$RANDOM,$RANDOM'\'[1,$n])

때로는 일부 요소가 동일한 정렬 키를 가지므로 모든 순열의 가능성이 동일하지 않으며 정렬 기능을 디렉터리 순서로 목록에 적용한 결과를 보존하는 쪽으로 약간의 편향이 있지만 편향은 작습니다. 나는 이것을 $RANDOM,$RANDOM정렬 키로 사용하고 있지만 $RANDOM편향을 줄이기 위한 것은 아닙니다. $RANDOM15자리 숫자이고 파일 수가 2^15에 가까워질수록 편향이 눈에 띄게 됩니다.

$RANDOM약간의 편향이 문제가 되지 않는 경우 샘플링에 충분합니다 . 보안과 관련된 어떤 것에도 적합하지 않습니다. 안전한 무작위 순열을 원하면 GNU coreutils를 사용하세요.shuf. (좋아하는 운영 체제에 기본 기능이 부족 shuf하고 어떤 이유로 GNU coreutils를 설치하고 싶지 않은 경우 다음을 시도해 볼 수 있습니다.이하라의 재깨달음대신에. )

securely_permuted=("${(0)$(printf '%s\0' *(N) | shuf -z))}")

또는 더 간단한 버전은 명령줄 길이 제한에 도달할 수 있습니다.

securely_permuted=("${(0)$(shuf -z -- *(N)))}")

1 실험적으로 순서는 안정적이지만(예: *(omoe\''REPLY=1'\')동일 *(om)) 순서가 *(oe\''REPLY=1'\')일치하지 않습니다 *(oN). 그럼에도 불구하고 이는 일부 특정 순서에 유리한 작은 편차입니다.

관련 정보