서브쉘이 없는 if 문 내에서 명령 출력 비교

서브쉘이 없는 if 문 내에서 명령 출력 비교

~에 따르면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내장되어 있습니다. 그 출력은 셸에 의해 생성되며 실제로 셸에서 해당 출력을 사용하기 위해 프로세스를 포크해야 하는 것은 약간 어리석은 느낌입니다.

일부 쉘( ksh93fish)은 거기에서 몇 가지 최적화를 구현합니다. $(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 varvar=$(line)bashzshprintf -v variable format argszshstatstrftime

일부 쉘은 일부 정보도 생성합니다.이미ksh's $SECONDS및 일부 다른 쉘에서 발견되는 일부 특수 변수 (및 , $RANDOM와 같은 표준 변수 (예: 's 와 동일 ))에서 자동으로 사용할 수 있습니다.$-$#fish(count $argv)

에서는 zsh이것이 대부분의 쉘 내부에 일반화되었으므로 내장 명령의 출력에 대해 명령 대체를 사용할 필요가 거의 없습니다. 예를 들어 내장 명령, 키워드, 명령 목록 등을 위한 연관 배열이 있습니다.

if (($+builtins[echo])); then
  echo echo is a builtin
fi

관련 정보