태그 보관물: sh

sh

“echo $ (stuff)”또는“echo`stuff`”에 어떤 문제가 있습니까? 잘못되었다고 들었습니다. 나쁜 습관, 비 우아하고

나는 다음 중 하나를 사용했다

echo $(stuff)
echo `stuff`

( stuff예를 들어 pwd또는 date더 복잡한 곳).

그런 다음이 구문이 잘못되었다고 들었습니다. 나쁜 습관, 비 우아하고 과도하며 중복 적이며 지나치게 복잡하며화물 컬트 프로그래밍, noobish, naive 등

그러나 명령 작동하므로 정확히 무엇입니까?



답변

tl; dr

발바닥 stuff가장 효과적 일 것입니다.



전체 답변

무슨 일이야

를 실행하면 다음 foo $(stuff)과 같은 일이 발생합니다.

  1. stuff 달리기;
  2. 출력 (stdout)은 인쇄되는 대신 $(stuff)다음을 호출하여 대체합니다 foo.
  3. 그런 다음 foo명령 줄 인수는 분명히 stuff반환 된 내용에 달려 있습니다 .

$(…)메커니즘을 “명령 대체”라고합니다. 귀하의 경우 기본 명령은 echo기본적으로 명령 줄 인수를 stdout에 인쇄하는 것입니다. 따라서 stuffstdout으로 인쇄하려고 시도하는 모든 것이 캡처 echo되어 stdout에 의해 인쇄됩니다 echo.

출력 stuff을 stdout으로 인쇄하려면 sole을 실행하십시오 stuff.

`…`구문은 $(…)같은 이름 으로 (동일한 이름 : “명령 대체”) 동일한 기능을 수행하지만 차이점은 거의 없으므로 맹목적으로 교환 할 수 없습니다. 참조 이 자주 묻는 질문이 질문을 .


echo $(stuff)무엇을 피해야 합니까?

echo $(stuff)하고있는 일을 알고 있다면 사용하고 싶은 이유가 있습니다 . 같은 이유로 echo $(stuff)당신이하고있는 일을 정말로 모른다면 피해야 합니다.

요점은 stuff하고 echo $(stuff)정확하게 해당되지 않습니다. 후자 stuff는 기본값 인의 출력에서 ​​split + glob 연산자를 호출하는 것을 의미 $IFS합니다. 명령 대체를 큰 따옴표로 묶으면이를 방지 할 수 있습니다. 명령 인용을 작은 따옴표로 묶으면 더 이상 명령을 대체하지 않습니다.

분할 할 때이를 관찰하려면 다음 명령을 실행하십시오.

echo "a       b"
echo $(echo "a       b")
echo "$(echo "a       b")"  # the shell is smart enough to identify the inner and outer quotes
echo '$(echo "a       b")'

그리고 globbing를 위해 :

echo "/*"
echo $(echo "/*")
echo "$(echo "/*")"  # the shell is smart enough to identify the inner and outer quotes
echo '$(echo "/*")'

보시다시피 echo "$(stuff)"(-ish *)와 같습니다 stuff. 당신은 그것을 사용할 수 있지만 이런 식으로 문제를 복잡하게 만드는 요점은 무엇입니까?

반면에 당신이 경우 원하는 의 출력은 stuff다음 글 로빙 분할 + 받아야 할 수 있습니다 찾을 수 echo $(stuff)유용합니다. 그래도 의식적인 결정이되어야합니다.

셸에서 평가하고 (분할, globbing 등을 포함하여) 출력을 생성하는 명령 eval "$(stuff)"이 있으므로 가능성이 있습니다 ( 이 답변 참조 ). 인쇄 하기 전에 추가 분할 + globbing을 수행하기 위해 출력이 필요한 명령을 본 적이 없습니다 . 의도적으로 사용하는 echo $(stuff)것은 매우 드문 것 같습니다.


무엇에 대해 var=$(stuff); echo "$var"?

좋은 지적. 이 스 니펫 :

var=$(stuff)
echo "$var"

echo "$(stuff)"equal (-ish *)와 동일 해야합니다 stuff. 전체 코드라면 stuff대신 실행하십시오 .

그러나 출력을 stuff두 번 이상 사용해야하는 경우이 접근법

var=$(stuff)
foo "$var"
bar "$var"

보통보다 낫다

foo "$(stuff)"
bar "$(stuff)"

하더라도 foo이다 echo당신이 얻을 echo "$var"코드에서,이 방법을 유지하는 것이 더있을 수 있습니다. 고려해야 할 사항 :

  1. 으로 var=$(stuff) stuff실행 번; 명령이 빠르더라도 동일한 출력을 두 번 계산하지 않는 것이 옳습니다. 또는 stuffstdout에 쓰는 것 (예 : 임시 파일 작성, 서비스 시작, 가상 머신 시작, 원격 서버에 알리기) 이외의 영향을 미치므로 여러 번 실행하고 싶지 않습니다.
  2. stuff시간 의존적이거나 다소 임의의 출력을 생성하는 경우 foo "$(stuff)"및 에서 일관되지 않은 결과를 얻을 수 있습니다 bar "$(stuff)". 이후 var=$(stuff)의 값 $var과 고정 당신은 확신 할 수 foo "$var"bar "$var"동일한 명령 행 인수를 얻을.

경우에 따라, 대신 여러 인수를 생성 하는 경우 (쉘이 지원하는 경우 배열 변수가 더 나을 수 있음 foo "$var") 대신 (필요한)을 사용할 수도 있습니다. 다시, 당신이하고있는 일을 알고 있습니다. 그것은 올 때 의 차이 와 사이과 동일 하고 .foo $varstufffooechoecho $varecho "$var"echo $(stuff)echo "$(stuff)"


* 동등한 ( -ish )?

나는 echo "$(stuff)"(-ish)와 동일 하다고 말했다 stuff. 정확히 동일하지 않은 두 가지 문제가 있습니다.

  1. $(stuff)하위 셸 stuff에서 실행 되므로 echo "$(stuff)"에 해당하는 (-ish)와 같습니다 (stuff). 서브 쉘 인 경우 실행되는 쉘에 영향을주는 명령은 기본 쉘에 영향을 미치지 않습니다.

    이 예 stuff에서 a=1; echo "$a":

    a=0
    echo "$(a=1; echo "$a")"      # echo "$(stuff)"
    echo "$a"
    

    그것을 비교

    a=0
    a=1; echo "$a"                # stuff
    echo "$a"
    

    a=0
    (a=1; echo "$a")              # (stuff)
    echo "$a"
    

    또 다른 예는,로 시작 stuff되는 cd /; pwd:

    cd /bin
    echo "$(cd /; pwd)"           # echo "$(stuff)"
    pwd
    

    테스트 stuff(stuff)버전.

  2. echo제어되지 않은 데이터를 표시하는 좋은 도구가 아닙니다 . 이것은 echo "$var"우리에 대해 얘기했다가되어 있어야합니다 printf '%s\n' "$var". 그러나 질문에 언급 echo되어 있고 가장 가능한 해결책은 echo처음에는 사용 하지 않기 때문에 printf지금까지 소개하지 않기로 결정했습니다 .

  3. stuff또는 (stuff)stdout 및 stderr 출력을 인터리브하는 동시에 echo $(stuff)모든 stderr 출력을 stuff(먼저 실행) 에서 인쇄 한 다음 stdout 출력을 echo(최종 실행)으로 인쇄합니다.

  4. $(…)후행 줄 바꿈을 제거한 다음 echo다시 추가합니다. 따라서 echo "$(printf %s 'a')" | xxd와 다른 출력을 제공합니다 printf %s 'a' | xxd.

  5. ls예를 들어 일부 명령 은 표준 출력이 콘솔인지 아닌지에 따라 다르게 작동합니다. 그래서 ls | cat동일하지 ls않습니다. 마찬가지로 echo $(ls)와 다르게 작동 ls합니다.

    퍼팅 ls일반적인 경우에, 옆 경우 이 다른 행동을 한 후 강제로 stuff | cat보다 더 나은 echo $(ls)또는 echo "$(ls)"이 다른 모든 문제는 여기에 언급 트리거하지 않기 때문에.

  6. 아마도 다른 종료 상태 (이 위키 답변의 완성을 위해 언급되었습니다. 자세한 내용 은 크레딧이 필요한 다른 답변 을 참조하십시오 ).


답변

또 다른 차이점 : 서브 쉘 종료 코드가 유실되므로 echo대신 종료 코드 가 검색됩니다.

> stuff() { return 1
}
> stuff; echo $?
1
> echo $(stuff); echo $?
0


답변