2014-06-05 8 views
4

설명 할 수없는 이상한 동작입니다. 예상 가능한 난수 시퀀스를 생성하기 위해 셸을 사용하고 싶습니다. $ RANDOM을 시드와 함께 사용합니다. 다음은 테스트 프로그램입니다.

RANDOM=15 
echo $RANDOM 

이 코드는 실행할 때마다 동일한 번호를 부여하여 올바르게 작동합니다. 그러나이 프로그램에 파이프를 추가하면 매번 다른 결과가 나타납니다. 다음과 같은 간단한 프로그램을 사용해보십시오.

RANDOM=15 
echo $RANDOM | cat 

문제점에 대한 2 개의 수정 사항을 발견했지만 예측할 수는 있지만 여전히 이유를 설명 할 수 없습니다.

수정 한

RANDOM=15 
x=$RANDOM 
echo $x | cat 

수정 2

(RANDOM=15 
echo $RANDOM) | cat 

나는 리눅스와 Mac에서 시도했다. 이 동작은 일관성이 있습니다. 누군가 설명 할 수 있니?

+2

(15) 후 첫 난수를 제공합니다 유도체). 이것은'shell '이 아니라'bash'라고 태그를 붙여야하고'/ bin/sh'로 시작하는 스크립트에서'RANDOM'을 사용하지 말아야합니다.'/ bin/sh' 통역사. –

답변

7

echo $RANDOM | cat과 같은 파이프 라인은 subshells을 만듭니다. 즉, 부모와 분기 된 별도의 프로세스이지만 exec() - 제품군 호출을 사용하여 다른 실행 가능 이미지로 대체되지는 않습니다. RANDOM이 명시 적으로 설정된 쉘과 동일한 쉘에서 분기 된 쉘 사이의 동작 차이를 관찰하고 있습니다.

해결 방법은 보조 쉘에서 $RANDOM의 평가를 부모 (첫 번째 경우)로 이동하거나 명시 적 시드 집합을 하위 셸 (두 번째 경우)로 이동하십시오.

+2

+1; 비 직관적 일 수있는 것에 대해 명시해야합니다 : 파이프 라인의 두 세그먼트'echo $ RANDOM | cat'은 서브 쉘에서 돌아갑니다. – mklement0

2

오른쪽 방향 (서브 쉘)을 가리키는 데 대한 Charles Duffy 감사합니다. 나는 bash의 src 코드에서 variable.c라는 파일을 발견했다. $ RANDOM은 함수가 호출되는 값을 얻기위한 "동적 변수"입니다. 이 함수는 $ RANDOM이 서브 쉘에서 처음 평가 될 때 랜덤 생성기를 다시 시드합니다.

// from bash-4.3/variables.c 

int 
get_random_number() 
{ 
    int rv, pid; 

    /* Reset for command and process substitution. */ 
    pid = getpid(); 
    if (subshell_environment && seeded_subshell != pid) 
    { 
     seedrand(); // <<<<==== re-seed! 
     seeded_subshell = pid; 
    } 

    do 
    rv = brand(); 
    while (rv == last_random_value); 
    return rv; 
} 

시드는 정적 변수이므로 각 쉘에는 자체 복사본이 있습니다. 서브 쉘에서 다시 시드하면 상위에 영향을주지 않습니다. 하위 셸에서 $ RANDOM 참조가 부모 셸의 시퀀스와 아무 관련이 없음을 보여주는 또 다른 테스트 사례가 있습니다. RANDOM`는 POSIX 쉬 기준 쉘 언어의 일부하지만 떠들썩한 파티에서 사용할 수있는 (그리고 아마도 다른 현대 ksh를 확장하지 않다`-

RANDOM=15 
echo $RANDOM $RANDOM 
RANDOM=15 
echo $RANDOM | cat 
echo $RANDOM 

마지막 줄은 참고

+0

서브 쉘에서 변경된 사항은 부모에게 영향을 미치지 않습니다. 놀랄 일도 아닙니다. 반대 동작 (예 : 공유 메모리 세그먼트 사용)을 구현하려면 상당한 노력 /주의가 필요합니다. 다시 시드 코드를 찾는 것이 좋은 방법입니다. +1! –