나는 다음 중 하나를 사용했다
echo $(stuff)
echo `stuff`
( stuff
예를 들어 pwd
또는 date
더 복잡한 곳).
그런 다음이 구문이 잘못되었다고 들었습니다. 나쁜 습관, 비 우아하고 과도하며 중복 적이며 지나치게 복잡하며화물 컬트 프로그래밍, noobish, naive 등
그러나 명령 이 작동하므로 정확히 무엇입니까?
답변
tl; dr
발바닥 stuff
이 가장 효과적 일 것입니다.
전체 답변
무슨 일이야
를 실행하면 다음 foo $(stuff)
과 같은 일이 발생합니다.
stuff
달리기;- 출력 (stdout)은 인쇄되는 대신
$(stuff)
다음을 호출하여 대체합니다foo
. - 그런 다음
foo
명령 줄 인수는 분명히stuff
반환 된 내용에 달려 있습니다 .
이 $(…)
메커니즘을 “명령 대체”라고합니다. 귀하의 경우 기본 명령은 echo
기본적으로 명령 줄 인수를 stdout에 인쇄하는 것입니다. 따라서 stuff
stdout으로 인쇄하려고 시도하는 모든 것이 캡처 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"
코드에서,이 방법을 유지하는 것이 더있을 수 있습니다. 고려해야 할 사항 :
- 으로
var=$(stuff)
stuff
실행 번; 명령이 빠르더라도 동일한 출력을 두 번 계산하지 않는 것이 옳습니다. 또는stuff
stdout에 쓰는 것 (예 : 임시 파일 작성, 서비스 시작, 가상 머신 시작, 원격 서버에 알리기) 이외의 영향을 미치므로 여러 번 실행하고 싶지 않습니다. stuff
시간 의존적이거나 다소 임의의 출력을 생성하는 경우foo "$(stuff)"
및 에서 일관되지 않은 결과를 얻을 수 있습니다bar "$(stuff)"
. 이후var=$(stuff)
의 값$var
과 고정 당신은 확신 할 수foo "$var"
와bar "$var"
동일한 명령 행 인수를 얻을.
경우에 따라, 대신 여러 인수를 생성 하는 경우 (쉘이 지원하는 경우 배열 변수가 더 나을 수 있음 foo "$var"
) 대신 (필요한)을 사용할 수도 있습니다. 다시, 당신이하고있는 일을 알고 있습니다. 그것은 올 때 의 차이 와 사이과 동일 하고 .foo $var
stuff
foo
echo
echo $var
echo "$var"
echo $(stuff)
echo "$(stuff)"
* 동등한 ( -ish )?
나는 echo "$(stuff)"
(-ish)와 동일 하다고 말했다 stuff
. 정확히 동일하지 않은 두 가지 문제가 있습니다.
-
$(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)
버전. -
echo
제어되지 않은 데이터를 표시하는 좋은 도구가 아닙니다 . 이것은echo "$var"
우리에 대해 얘기했다가되어 있어야합니다printf '%s\n' "$var"
. 그러나 질문에 언급echo
되어 있고 가장 가능한 해결책은echo
처음에는 사용 하지 않기 때문에printf
지금까지 소개하지 않기로 결정했습니다 . -
stuff
또는(stuff)
stdout 및 stderr 출력을 인터리브하는 동시에echo $(stuff)
모든 stderr 출력을stuff
(먼저 실행) 에서 인쇄 한 다음 stdout 출력을echo
(최종 실행)으로 인쇄합니다. -
$(…)
후행 줄 바꿈을 제거한 다음echo
다시 추가합니다. 따라서echo "$(printf %s 'a')" | xxd
와 다른 출력을 제공합니다printf %s 'a' | xxd
. -
ls
예를 들어 일부 명령 은 표준 출력이 콘솔인지 아닌지에 따라 다르게 작동합니다. 그래서ls | cat
동일하지ls
않습니다. 마찬가지로echo $(ls)
와 다르게 작동ls
합니다.퍼팅
ls
일반적인 경우에, 옆 경우 이 다른 행동을 한 후 강제로stuff | cat
보다 더 나은echo $(ls)
또는echo "$(ls)"
이 다른 모든 문제는 여기에 언급 트리거하지 않기 때문에. -
아마도 다른 종료 상태 (이 위키 답변의 완성을 위해 언급되었습니다. 자세한 내용 은 크레딧이 필요한 다른 답변 을 참조하십시오 ).
답변
또 다른 차이점 : 서브 쉘 종료 코드가 유실되므로 echo
대신 종료 코드 가 검색됩니다.
> stuff() { return 1
}
> stuff; echo $?
1
> echo $(stuff); echo $?
0