~에 따르면https://www.gnu.org/software/bash/manual/bashref.html#Command-Grouping
중괄호 사이에 명령 목록을 배치하면 해당 목록이 현재 셸의 컨텍스트에서 실행됩니다.
하지만 이것을 시도하면 if [[ { type -t echo; } = "builtin" ]]; then echo 1; else echo 0; fi
다음과 같은 오류가 발생합니다.
-bash: 조건부 이항 연산자가 필요합니다.
-bash: "type" 근처에 구문 오류가 있습니다.
괜찮아요, 이런 식으로 사용하면 안 된다는 걸 알아요. 이제 if [[ $( type -t echo ) = "builtin" ]]; then echo 1; else echo 0; fi
이론적 으로 .
서브셸의 불필요한 사용을 방지하는 방법에 대한 다른 질문에 대한 답변을 찾았지만 그 중 어느 것도 서브셸 없이 명령의 출력을 비교하는 방법을 설명하지 않았습니다. 내가 정말로 원하는 것은 필요하지 않은 서브쉘을 사용하지 않는 것이며, 가능하다면 현재 쉘 컨텍스트에서 이 검사를 실행하고 싶습니다. 그렇게 해야 한다고 느껴집니다. PS 다른 방법이 없다면 변수와 연산을 사용해도 괜찮습니다.
답변1
명령의 출력을 얻으려면 어떻게든 읽어야 합니다. type
표준 출력에 씁니다. 어떻게든 가져와서 [
명령 에 전달해야 합니다 .
$(...)
이를 위해 파이프를 사용하십시오. 그러나 파이프의 경우 작성기와 판독기 프로세스가 필요하므로 내장 명령을 실행하는 경우에도 프로세스를 분기해야 합니다. 동일한 프로세스에서 파이프를 읽고 쓰려고 시도할 수 있지만 아무도 읽지 않으면 쓰기가 차단될 수 있기 때문에 종종 교착 상태가 발생하기 쉽습니다(이런 일이 발생하려면 파이프 버퍼를 채워야 하지만 이는 일어날 가능성이 낮습니다 type
).
yash
원시 인터페이스가 있는 셸을 사용하여 이 작업을 수행할 수 있습니다 pipe()
.
{
type echo >&3
echo 3>&- # close the writing end so the reader can see an eof
IFS= read -r answer <&4
} 3>>|4
type
위에서 출력이 파이프 버퍼 크기(최신 버전의 Linux에서 기본값은 64KiB)보다 크면 교착 상태가 발생합니다.
를 사용하면 bash
언제든지 다음을 수행할 수 있습니다.
type -t echo > file
IFS= read -rd '' type < file
if [ "$type" = builtin ]...
그러나 이는 서브셸을 방지하지만 파일 시스템이 file
.
이것은 type
내장되어 있습니다. 그 출력은 셸에 의해 생성되며 실제로 셸에서 해당 출력을 사용하기 위해 프로세스를 포크해야 하는 것은 약간 어리석은 느낌입니다.
일부 쉘( ksh93
및 fish
)은 거기에서 몇 가지 최적화를 구현합니다. $(type echo)
( (type echo)
in ) 에서 fish
그들은 실제로 출력의 쓰기 및 읽기를 위조합니다(FreeBSD는 sh
또한 단일 내장 호출에 대해 이 작업을 수행합니다( type
여기처럼)). 내장 함수의 stdout이 명령 대체인 경우 쉘은 출력을 작성하지 않지만 가능한 출력의 텍스트를 명령 대체 결과에 추가하므로 포크가 필요하지 않습니다.
실제로 fish
's는 하위 쉘 환경도 생성하지 않는다는 점에서 's (type echo)
와 더 유사합니다 . 그리고 ,ksh93
${ type echo;}
$(...)
ksh93
본뜨다하위 프로세스가 내부 코드를 해석하기 위해 분기된 것처럼 나타나도록 하는 하위 쉘 환경이며, 변형에는 그렇게 하지 않습니다 ${ ...;}
.
ksh93$ a=1
ksh93$ echo "$(a=2; type echo) $a"
echo is a shell builtin 1
ksh93$ echo "${ a=3; type echo;} $a"
echo is a shell builtin 3
fish> set a 1
fish> echo (set a 2; type echo) $a
echo is a builtin 2
최적화되지 않은 일부 쉘에서는 결과를 작성하지 않고 변수에 저장하여 많은 내장 함수를 호출할 수 있습니다.
가장 확실한 것은 표준 read
이며 기본적으로 이 작업을 수행합니다( 대신 getopts
이 작업을 수행합니다 ). 그리고 . , ... 내장 함수를 사용하여 동일한 작업을 수행할 수 있습니다.IFS= read -r var
var=$(line)
bash
zsh
printf -v variable format args
zsh
stat
strftime
일부 쉘은 일부 정보도 생성합니다.이미ksh
's $SECONDS
및 일부 다른 쉘에서 발견되는 일부 특수 변수 (및 , $RANDOM
와 같은 표준 변수 (예: 's 와 동일 ))에서 자동으로 사용할 수 있습니다.$-
$#
fish
(count $argv)
에서는 zsh
이것이 대부분의 쉘 내부에 일반화되었으므로 내장 명령의 출력에 대해 명령 대체를 사용할 필요가 거의 없습니다. 예를 들어 내장 명령, 키워드, 명령 목록 등을 위한 연관 배열이 있습니다.
if (($+builtins[echo])); then
echo echo is a builtin
fi