“echo $ (stuff)”또는“echo`stuff`”에 어떤 문제가 있습니까?


31

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

echo $(stuff)
echo `stuff`

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

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

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


11
중복되므로 사용해서는 안됩니다. 쓸모없는 고양이 사용과 비교 : porkmail.org/era/unix/award.html
dr01

7
echo $(echo $(echo $(echo$(echo $(stuff)))))또한 않는 권리, 일을하고, 여전히 당신은 아마 그것을 사용하지 않을까요? ;-)
Monica

1
그 확장으로 정확히 무엇을하려고합니까?
curiousguy

@ curiousguy 다른 사용자를 돕기 위해 노력하고 있으므로 아래 답변입니다. 최근 에이 구문을 사용하는 질문이 세 개 이상 있습니다. 그들의 저자는 다양한 노력을 기울이고있었습니다 stuff. : D
Kamil Maciorowski

2
또한, 자신을 반향 실에 한정하는 것이 현명하지 않다는 데 모두 동의하지 않습니까? ;-)
복직 자 Monica

답변:


63

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


5
또 다른 차이점 stuff은 인터리브 stdoutstderr출력 방식 이며 에서의 echo `stuff` 모든 stderr출력을 출력 stuff한 다음 stdout출력 만 인쇄합니다 .
Ruslan

3
그리고 이것은 또 다른 예입니다 : bash 스크립트에는 인용 부호가 너무 많을 수 없습니다. echo $(stuff)echo "$(stuff)"로빙 및 확장을 명시 적으로 원하지 않는 것처럼 훨씬 더 많은 문제를 일으킬 수 있습니다 .
rexkogitans

2
한 가지 더 작은 차이점 : $(…)후행 줄 바꿈을 제거한 다음 echo다시 추가합니다. 따라서 echo "$(printf %s 'a')" | xxd와 다른 출력을 제공합니다 printf %s 'a' | xxd.
derobert

1
ls표준 출력이 콘솔인지 아닌지에 따라 일부 명령 ( 예 :)이 다르게 작동 한다는 것을 잊지 마십시오. 그래서 ls | cat동일하지 ls않습니다. 물론 echo $(ls)다른 방식으로 작동 ls합니다.
Martin Rosenau

@Ruslan 이제 답변은 커뮤니티 위키입니다. 나는 당신의 유용한 의견을 위키에 추가했습니다. 고맙습니다.
Kamil Maciorowski

5

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

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

3
슈퍼 유저에 오신 것을 환영합니다! 당신이 보여주는 차이점 을 설명 할 수 있습니까 ? 감사
bertieb

4
나는이 쇼가 리턴 코드가 있다고 생각 $?의 리턴 코드가 될 것이다 echo(대한 echo $(stuff)대신 하나) return에 의해 에드 stuff. stuff기능 return 1(종료 코드), 그러나 echo관계없이 리턴 코드의 "0"설정은 stuff. 여전히 대답에 있어야합니다.
Ismael Miguel

서브 쉘에서 반환 값은 손실되었습니다
phuclv
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.