명령 행 출력을 캡처하는 두 가지 방법이 있습니다 bash
.
-
레거시 Bourne 쉘 백틱
``
:var=`command`
-
$()
구문 (내가 아는 한 Bash에만 해당되거나 최소한 원래 Bourne과 같은 POSIX가 아닌 오래된 쉘에서는 지원되지 않음)var=$(command)
백틱과 비교하여 두 번째 구문을 사용하면 어떤 이점이 있습니까? 아니면 두 사람이 완전히 100 % 동일합니까?
답변
주요한 것은 명령에 명령 을 중첩 시킬 수 있다는 것인데, 어떤 형태의 이스케이프가 백틱에서 작동하는지 알아 내려고 노력하는 정신을 잃지 않고 명령 내에 명령을 내릴 수 있습니다.
예를 들어, 다소 고안되었다.
deps=$(find /dir -name $(ls -1tr 201112[0-9][0-9]*.txt | tail -1l) -print)
/dir
2011 년 12 월 (a) 의 가장 오래된 날짜의 텍스트 파일과 이름이 같은 디렉토리 트리 의 모든 파일 목록이 제공됩니다 .
또 다른 예는 상위 디렉토리의 이름 (전체 경로가 아님)을 얻는 것과 같습니다.
pax> cd /home/pax/xyzzy/plugh
pax> parent=$(basename $(dirname $PWD))
pax> echo $parent
xyzzy
(a) 이제 특정 명령이 실제로 작동하지 않을 수 있으므로 기능을 테스트하지 않았습니다. 그래서, 당신이 저에게 투표를한다면, 의도를 잃어버린 것입니다. 🙂 그것은 버그가없는 프로덕션 레디 스 니펫이 아니라 어떻게 네 스팅을 할 수 있는지에 대한 예시입니다.
답변
gcc
설치된 위치에 해당하는 lib 디렉토리를 찾으려고 가정하십시오 . 선택하실 수 있습니다 :
libdir=$(dirname $(dirname $(which gcc)))/lib
libdir=`dirname \`dirname \\\`which gcc\\\`\``/lib
첫 번째는 두 번째보다 쉽습니다. 첫 번째를 사용하십시오.
답변
백틱 ( `...`
)은 가장 오래된 비 POSIX 호환 bourne-shell에만 필요한 레거시 구문 $(...)
이며 POSIX이며 몇 가지 이유로 더 선호됩니다.
-
\
백틱 내부의 백 슬래시 ( )는 명확하지 않은 방식으로 처리됩니다.$ echo "`echo \\a`" "$(echo \\a)" a \a $ echo "`echo \\\\a`" "$(echo \\\\a)" \a \\a # Note that this is true for *single quotes* too! $ foo=`echo '\\'`; bar=$(echo '\\'); echo "foo is $foo, bar is $bar" foo is \, bar is \\
-
중첩 된 인용문
$()
이 훨씬 더 편리합니다.echo "x is $(sed ... <<<"$y")"
대신에:
echo "x is `sed ... <<<\"$y\"`"
또는 다음과 같은 것을 작성하십시오.
IPs_inna_string=`awk "/\`cat /etc/myname\`/"'{print $1}' /etc/hosts`
$()
인용을 위해 완전히 새로운 맥락을 사용 하기 때문에Bourne 및 Korn 쉘에는 이러한 백 슬래시가 필요하지만 Bash 및 대시는 필요하지 않으므로 이식성이 없습니다.
-
중첩 명령 대체 구문이 더 쉽습니다.
x=$(grep "$(dirname "$path")" file)
보다:
x=`grep "\`dirname \"$path\"\`" file`
때문에
$()
각 명령의 대체가 보호되고 인용과 이스케이프 이상 특별한 문제없이 자체적으로 처리 할 수 있도록 인용에 대한 완전히 새로운 상황 시행한다. 백틱을 사용하는 경우 레벨이 2 이상이되면 배가 더 나빠집니다.몇 가지 더 많은 예 :
echo `echo `ls`` # INCORRECT echo `echo \`ls\`` # CORRECT echo $(echo $(ls)) # CORRECT
-
역 따옴표를 사용할 때 일관되지 않은 동작 문제를 해결합니다.
echo '\$x'
출력\$x
echo `echo '\$x'`
출력$x
echo $(echo '\$x')
출력\$x
-
Backticks 구문에는 포함 된 명령의 내용에 대한 기록 제한이 있으며, 역 따옴표를 포함하는 일부 유효한 스크립트를 처리 할 수 없지만 최신
$()
양식은 모든 종류의 유효한 포함 된 스크립트를 처리 할 수 있습니다.예를 들어, 유효한 다른 내장 스크립트는 왼쪽 열에서 작동하지 않지만 오른쪽 IEEE 에서는 작동합니다 .
echo ` echo $( cat <<\eof cat <<\eof a here-doc with ` a here-doc with ) eof eof ` ) echo ` echo $( echo abc # a comment with ` echo abc # a comment with ) ` ) echo ` echo $( echo '`' echo ')' ` )
따라서 $
-prefixed 명령 대체 구문 은 선호하는 방법이어야합니다. 깨끗한 구문으로 시각적으로 명확하고 (인간 및 기계 가독성 향상) 중첩 가능하고 직관적이며 내부 구문 분석이 분리되어 있으며보다 일관성이 있습니다. 큰 따옴표 내에서 구문 분석되는 다른 모든 확장) (예 : 백틱이 유일한 예외이고 `
문자가 인접 해있을 때 문자가 쉽게 위장 "
되어 특히 작거나 특이한 글꼴로 읽기가 더 어려워 짐)
출처 : 왜 $(...)
선호하는 이유는 무엇입니까 `...`
(백틱)? BashFAQ에서
또한보십시오:
답변
남자 배쉬에서 :
$(command)
or
`command`
Bash performs the expansion by executing command and replacing the com-
mand substitution with the standard output of the command, with any
trailing newlines deleted. Embedded newlines are not deleted, but they
may be removed during word splitting. The command substitution $(cat
file) can be replaced by the equivalent but faster $(< file).
When the old-style backquote form of substitution is used, backslash
retains its literal meaning except when followed by $, `, or \. The
first backquote not preceded by a backslash terminates the command sub-
stitution. When using the $(command) form, all characters between the
parentheses make up the command; none are treated specially.
답변
다른 답변 외에도
$(...)
시각적으로 눈에 띄는 것보다
`...`
백틱은 아포스트로피처럼 보입니다. 사용중인 글꼴에 따라 다릅니다.
(방금 알았 듯이 백틱은 인라인 코드 샘플에 입력하기가 훨씬 어렵습니다.)
답변
$()
중첩을 허용합니다.
out=$(echo today is $(date))
나는 백틱이 그것을 허용하지 않는다고 생각합니다.
답변
$(command)
명령 대체 형식 을 정의하는 것이 POSIX 표준입니다 . 오늘날 사용되는 대부분의 쉘은 POSIX를 준수하며 기존의 백틱 표기법보다 선호되는 형식을 지원합니다. 쉘 언어 문서 의 명령 대체 섹션 (2.6.3)은 다음을 설명합니다.
명령 대체는 명령 이름 대신 명령 출력을 대체 할 수있게합니다. 명령 대체는 명령이 다음과 같이 묶여있을 때 발생합니다.
$(command)
또는 (backquoted version) :
`command`
쉘
은 서브 쉘 환경에서 명령 을 실행 하고 ( 쉘 실행 환경 참조 ) 명령 대체 ( 명령 텍스트와 “$ ()”또는 역 따옴표)를 명령의 표준 출력으로 대체하여 명령 대체를 확장해야합니다.<newline>
대체가 끝날 때 하나 이상의 문자 시퀀스 .<newline>
출력이 끝나기 전에 포함 된 문자는 제거되지 않아야합니다. 그러나 IFS의 값과 인용에 따라 필드 구분 기호로 필드 구분 기호로 처리되어 제거 될 수 있습니다. 출력에 널 바이트가 포함되어 있으면 동작이 지정되지 않은 것입니다.역 인용 된 명령 대체 스타일 내에서
<backslash>
‘$
‘, ‘`
‘또는
뒤에 오는 경우를 제외하고 문자 그대로의 의미를 유지해야합니다<backslash>
. 일치하는 역 따옴표에 대한 검색은 인용되지 않은 첫 번째 인용되지 않은 역 따옴표에 의해 충족되어야합니다. 이 검색 중에 이스케이프 처리되지 않은 역 따옴표가 쉘 주석, 여기 문서, $ ( command ) 형식 의 내장 명령 대체 또는 인용 된 문자열에서 발견되면 정의되지 않은 결과가 발생합니다. ”`...`
“시퀀스 내에서 시작하지만 끝나지 않는 작은 따옴표 또는 큰 따옴표 문자열 은 정의되지 않은 결과를 생성합니다.$ ( command ) 형식을 사용하면 여는 괄호 뒤에 나오는 닫는 괄호 뒤에있는 모든 문자가 command를 구성합니다
. 지정되지 않은 결과를 생성하는 리디렉션만으로 구성된 스크립트를 제외하고 유효한 쉘 스크립트를 command에 사용할 수 있습니다 .추가 틸드 확장, 파라미터 확장, 명령 대체 또는 산술 확장을 위해 명령 대체의 결과가 처리되지 않아야합니다. 큰 따옴표 안에 명령 대체가 발생하면 대체 결과에 대해 필드 분할 및 경로 이름 확장을 수행하지 않아야합니다.
명령 대체는 중첩 될 수 있습니다. 역 인용 버전 내에서 중첩을 지정하려면 응용 프로그램은 내부 역 인용 부호 앞에
<backslash>
문자를 사용해야 합니다. 예를 들면 다음과 같습니다.
\`command\`
쉘 명령 언어의 구문에는 “로 시작하는 확장에 대한 모호성이 있습니다.
$((
하위 쉘로 시작하는 산술 확장 또는 명령 대체를 도입 할 수 있습니다. 산술 확장이 우선합니다. 즉, 쉘은 먼저 확장을 산술 확장으로 구문 분석 할 수 있는지 여부를 판별하고 확장을 명령으로 구문 분석해야합니다. 확장을 산술 확장으로 구문 분석 할 수없는 것으로 판단되는 경우 쉘은이 결정을 수행 할 때 중첩 된 확장을 평가할 필요가 없습니다. 확장을 산술 확장으로 구문 분석 할 수 없다고 결정하지 않고 입력 종료가 발생하면 쉘은 확장을 불완전한 산술 확장으로 취급하고 구문 오류를보고해야합니다. 적합한 응용 프로그램은 “$(
“와 “(
하위 쉘로 시작하는 명령 대체에서 두 개의 토큰 (즉, 공백으로 분리)으로 구분됩니다. 예를 들어, 단일 서브 쉘을 포함하는 명령 대체는 다음과 같이 작성 될 수 있습니다.
$( (command) )