같은 줄에 변수를 할당한 후 명령을 실행하는 이식성을 다루는 표준이 있습니까?
APPLE="cider" echo hi
이런 것이 얼마나 휴대성이 좋을까요? 어디에서 작동하고 어디에서 작동하지 않습니까?
또한 내 쉘 스크립트는 #!/bin/sh로 시작합니다.
답변1
POSIX 호환 쉘을 사용한다면 괜찮습니다.
~에서쉘 명령 언어의 POSIX 정의:(해당 사항은 굵은 글씨로 표시)
"간단한 명령"은 일련의선택적 변수 할당임의의 순서로 리디렉션하고 선택적으로 제어 연산자에 의해 종료되는 단어와 리디렉션이 뒤따릅니다.
주어진 단순 명령을 실행해야 하는 경우(즉, 단순 명령이 조건부 구조(예: AND-OR 목록 또는 Case 문)에 의해 우회되지 않는 경우) 다음 확장, 할당 및 리디렉션은 다음에서 수행되어야 합니다. 명령 텍스트의 시작부터 끝까지 :
변수 할당으로 인식되는 단어또는 리디렉션을 기반으로쉘 구문 규칙3단계와 4단계의 처리를 위해 저장합니다.
변수 할당이나 리디렉션이 아닌 단어는 확장되어야 합니다. 확장 후 남은 필드가 있는 경우 첫 번째 필드는 명령 이름으로 처리되어야 하며 나머지 필드는 명령에 대한 인수입니다.
리디렉션은 다음에 설명된 대로 수행되어야 합니다.리디렉션.
물결표 확장, 매개변수 확장, 명령 대체, 산술 확장 및 따옴표 제거를 할당하기 전에 모든 변수 할당을 확장해야 합니다.
이전 목록에서 특수 내장 유틸리티를 처리하기 위해 3단계와 4단계의 순서를 반대로 할 수 있습니다.특수 내장 유틸리티.
명령 이름 결과가 없으면 변수 할당은 현재 실행 환경에 영향을 미칩니다. 그렇지 않으면,변수 할당은 명령 실행 환경에 대해 내보내야 하며 현재 실행 환경에 영향을 주어서는 안 됩니다.(특수 내장 제외)
또한 #!/bin/sh
매우 중요합니다. ~에서POSIX 정의sh
:
sh 유틸리티는 명령줄 문자열, 표준 입력 또는 지정된 파일에서 읽은 명령을 실행하는 명령 언어 해석기입니다. 애플리케이션은 다음을 보장해야 합니다.실행될 명령은 설명 언어로 표현됩니다.쉘 명령 언어.
sh
따라서 기본적으로 위에서 소개한 규칙을 따라야 한다고 말합니다 .
따라서 POSIX 호환 운영 체제를 사용하는 한 괜찮습니다.
답변2
두 번째 질문에 대한 답은 불완전합니다(포탄 수는 다음과 같습니다).믿을 수 없는)
% for sh in dash ksh93 mksh rc fish bash zsh csh tcsh jsh; do
printf '%s\n' "$sh: $($sh -c 'var=foo echo hi')"
done
dash: hi
ksh93: hi
mksh: hi
rc: hi
fish: Unknown command “var=foo”. Did you mean “set var foo”? For information on assigning values to variables, see the help section on the set command by typing “help set”
Standard input: var=foo echo hi
^
fish:
bash: hi
zsh: hi
var=foo: Command not found.
csh:
var=foo: Command not found.
tcsh:
jsh: hi
이것은 대부분의 현대 Korn 유사 쉘에서 작동합니다. 하지만 나는 그것이 표준이라고 생각하지 않습니다. 어떤 사람들은 좋아할 것이라고 확신합니다.스티븐 차제라스얼마나 흔한 일인지 알게 될 것입니다.
답변3
응, 옛날부터 그랬어.sh
The environment for any simple-command may be
augmented by prefixing it with one or more
assignments to parameters. Thus these two lines
are equivalent
TERM=450 cmd args
(export TERM; TERM=450; cmd args)
답변4
주어진 예의 명령이 echo
실행되지만 발생하는 상황은 $APPLE
약간 복잡합니다.
@Patrick의 답변에서 알 수 있듯이 쉘이 프로세스를 호출하는 경우 호출 전에 명령줄에 선언된 모든 변수가 해당 환경으로 내보내기 위해 지정되는 경우가 있습니다. 또한 이러한 변수는 호출 프로세스와 함께 만료되도록 지정됩니다. 따라서...
unset var; var=val cmd; echo ${var-unset.}
...인쇄해야 함unset.
그러나 귀하의 예에서 볼 수 있듯이 전체 개념은 약간 복잡해지며 이 시점 cmd
에서아니요호출된 프로세스이지만 쉘 내장, 쉘 함수 또는특별한쉘 내장 유틸리티. 이 세 가지 경우 각각에서 셸은 메모리에서 자체 루틴을 실행하고 아무것도 호출하지 않을 가능성이 높습니다.
echo
예 를 들어,거의 확실히쉘 내장 유틸리티 - 내가 아는 대부분의 쉘이 제공하는 것처럼 - 하지만아니요POSIX 지정특별한내장. 따라서 이는 기본적으로 외부 실행 파일을 에뮬레이트해야 하는 쉘 함수입니다. 이렇게 하면 더 명확해질 수 있습니다.여기:
"내장"이라는 용어는 쉘이 유틸리티를 검색하지 않고 직접 실행할 수 있음을 의미합니다. 구현에서는 모든 유틸리티를 내장하도록 선택할 수 있습니다. 그러나 여기에 설명된 특수 내장 유틸리티는 일반 내장 유틸리티와 동일하지 않습니다.
특수 내장 유틸리티를 사용하여 지정된 변수 할당은 내장 완료 후에도 유지됩니다. 이는 일반 내장 유틸리티나 기타 유틸리티의 경우에는 해당되지 않습니다.
이 섹션의 특수 내장 유틸리티는 POSIX.1-2008 시스템 인터페이스 볼륨에 정의된 exec 기능 계열을 통해 액세스할 수 있는 방식으로 제공될 필요가 없습니다.
echo
따라서 의 명령줄에 선언된 변수는 함께 사라지 echo
지만 set
의 명령줄에 선언된 변수는 여전히 존재합니다.( bash
이 규칙은 기본적으로 위반되지만). a인 경우에도 cmd
마찬가지입니다.껍데기기능:
함수가 실행되면 구문 오류가 발생해야 하며특수 내장 유틸리티로 설명되는 변수에 속성 할당특수 내장 유틸리티 시작 부분의 열거 목록.