지역 변수를 정의하기 위해 "local" 키워드를 지원하는 쉘 목록

지역 변수를 정의하기 위해 "local" 키워드를 지원하는 쉘 목록

Bash와 Zsh가 변수를 지원한다는 것을 알고 있지만 local일부 시스템에는 POSIX 호환 셸만 있습니다. localPOSIX 쉘에서는 정의되지 않았습니다 .

local그렇다면 어떤 쉘이 지역 변수의 키워드 정의를 지원하는지 묻고 싶습니다 .

편집하다: 쉘에 관해서는 기본 /bin/sh쉘을 참조합니다.

답변1

이는 local지원 또는 비지원만큼 간단하지 않습니다. 구문에는 다양한 변형이 있으며 하나 또는 다른 형태의 로컬 범위를 사용하는 셸 간에 실행되는 방법도 있습니다.

그렇기 때문에 모두가 동의할 수 있는 기준을 세우는 것이 어렵습니다. 바라보다http://austingroupbugs.net/bug_view_page.php?bug_id=767이 분야에 대한 POSIX의 노력에 감사드립니다.

로컬 범위는 1980년대 초 ksh에 처음 추가되었습니다.

함수에서 지역 변수를 선언하는 구문은 다음과 같습니다 typeset.

function f {
  typeset var=value
  set -o noglob # also local to the function
  ...
}

(함수 지원은 나중에 Bourne 쉘에 추가되었지만 다른 구문( f() command) 을 사용했으며 ksh해당 구문에 대한 지원도 나중에 추가되었습니다. Bourne 쉘에는 로컬 범위가 없었습니다(물론 서브 쉘을 통한 경우 제외))

AFAIK 내장 기능은 local1989년에 Almquist 쉘(BSD, dash, busybox sh에서 사용됨)에 처음 추가되었지만 ksh크게 다르게 작동합니다 typeset. 파생 상품은 별칭을 로 ash지원하지 않지만 언제든지 수동으로 정의할 수 있습니다.typesetlocal

별칭은 각각 1989년과 1991년에 bash와 zsh에 추가되었습니다 typeset.local

ksh88은 1990년경에 local문서화되지 않은 별칭으로 추가되었고 typeset1994년에는 pdksh 및 그 파생물로 추가되었습니다. posh(기반 pdksh) 제거되었습니다 (필요 하지만 필수는 아닌 typeset경우 데비안 정책을 엄격히 준수하기 위해 ).localtypeset

지정에 대한 POSIX의 초기 반대 typeset는 다음과 같았다.동적범위 지정. 따라서 ksh93(David Korn의 1993년 ksh 재작성)은 다음으로 변경되었습니다.변화 없는대신 범위 지정. 또한 ksh93에서는 ksh88과 달리 Bourne 구문 ksh( ) 대신 구문( ) 을 사용하여 function f {...}선언된 함수에 대해서만 로컬 범위 지정이 수행 되며 Aliasing이 제거되었습니다.f() {...}local

local그러나 AT&T의 ksh93v -beta typeset및 최종 버전은 . 이 경우와의 차이점은 함수 내부에서만 호출할 수 있다는 것입니다.ksh93bashlocaltypesetbashksh2020에서는 기본적으로 비활성화되어 있습니다 .하지만local/alias Bash 모드가 컴파일되지 않은 declare경우에도typeset(여전히 정적 범위가 있지만).

yashtypeset(매우 늦게 작성됨) (à la ksh88) 이 있지만 local버전 2.48(2018년 12월) 이후에는 별칭으로만 사용되었습니다.

@힐리(슬프게도 누구지?2021년에 사망)는 최근 POSIX와 호환되는 Bourne 쉘의 자손을 유지하는 데 사용됩니다.boshlocal로컬 범위( 유사 )는 버전 2016-07-06부터 지원됩니다 ash.

따라서 어떤 형태의 지역 변수 범위 지정을 사용하는 오늘날의 Bourne과 같은 쉘은 다음과 같습니다.

  • ksh, 모든 구현 및 그 파생물(ksh88, ksh93, pdksh 및 posh, mksh, OpenBSD sh 등과 같은 파생물).
  • ash 및 모든 파생물(NetBSD sh, FreeBSD sh, dash, busybox sh)
  • 세게 때리다
  • 다루기 힘든
  • 야쉬
  • 보쉬

다양한 시스템의 경우 일부 시스템(대부분)에는 shPOSIX가 포함되어 있고 다른 시스템에는 포함되어 있지 않습니다(예: Solaris). 다양한 시스템에 구현하기 위해 다음을 갖추고 있습니다.sh/bin/usr/xpg4/binsh

  • ksh88: 대부분의 SysV 파생 상용 Unices(AIX, HP/UX, Solaris1...)
  • bash: 대부분의 GNU/Linux 시스템, Cygwin, macOS
  • ash: 기본적으로 Debian 및 대부분의 파생 제품(Ubuntu, Linux/Mint 포함)에서 관리자는 이를 bash 또는 mksh로 변경할 수 있습니다. NetBSD, FreeBSD 및 일부 파생 제품(macOS 제외)
  • busybox sh: 대부분은 아니지만 많은 임베디드 Linux 시스템
  • pdksh 또는 파생물: OpenBSD, MirBSD, Android

이제 차이점은 다음과 같습니다.

  • typeset(ksh, pdksh, bash, zsh, yash) 및 local(ksh88, pdksh, bash, zsh, ash, yash 2.48+).
  • 지원되는 옵션 목록입니다.
  • 정적(ksh93, function f {...}함수 내) 및 동적 범위(다른 모든 셸). 예를 들어, function f { typeset v=1; g; echo "$v"; }; function g { v=2; }; f출력 1과 . 이 속성이 에 어떤 영향을 미치는지도 2참조하세요 .exportksh93
  • 뭐든지 local/ typeset그냥 변수를 만드세요현지의( ash, bosh) 또는 변수의 새 인스턴스를 생성합니다(다른 쉘). 예를 들어 또는 v=1; f() { local v; echo "${v:-empty}"; }; f출력 여부 ( bash 5.0 이상의 옵션 참조 ).1emptylocalvar_inherit
  • 새 변수를 생성하는 변수의 경우 새 변수가 상속되는지 여부속성(예: export) 및/또는 유형과 상위 범위의 변수에서 가져온 유형입니다. 예를 들어 export V=1; f() { local V=2; printenv V; }; f인쇄 할지 1아니면 2아무것도 인쇄할지 여부입니다.
  • 이 새 변수에 초기 값(유형에 따라 null, 0, 빈 목록 zsh)이 있는지 아니면 처음에 설정되지 않았는지 여부입니다.
  • unset V해당 변수를 로컬 범위의 변수에 그대로 둘지 unset아니면 그냥 둘지 여부껍질첫 번째 수준 범위(경우에 따라 mksh, yash, bash). 예를 들어 v=1; f() { local v=2; unset v; echo "$v"; }출력 여부( bash 5.0 이상의 옵션 1참조 )localvar_unset
  • for 와 마찬가지로 export키워드인지, 내장 키워드인지, 아니면 둘 다인지, 그리고 어떤 조건에서 키워드로 간주되는지를 확인하세요.
  • for 와 마찬가지로 export인수가 일반 명령 인수 또는 할당된 값으로 구문 분석되는지 여부(및 어떤 조건에서)입니다.
  • 당신은 말할 수 있습니까?현지의상위 범위에서 읽기 전용인 변수입니다.
  • v=value myfunction자체가 로컬 또는 비로컬로 myfunction선언된 위치와의 상호 작용 .v

그게 내가 지금 생각하는 전부입니다. 자세한 내용은 위의 Austin 그룹 오류를 확인하세요.

쉘의 로컬 범위에 관해서옵션(대변하기 쉬운), 이를 지원하는 쉘은 다음과 같습니다.

  • ksh88(두 개의 함수 정의 구문 사용): 기본적으로 수행되지만 비활성화할 수 있는 방법은 없습니다.
  • ash(1989년 이후): 와 동일합니다 local -. $-매개변수(저장된 옵션 목록)를 로컬 매개변수로 설정합니다.
  • ksh93function f {...}: 이제 기능에 대해서만 수행됩니다.
  • zsh(1995년부터). 그리고 setopt localoptions. emulate -L시뮬레이션 모드(및 해당 옵션 세트)를 기능 현지화로 설정할 수도 있습니다 .
  • bash(2016년부터) 과 local -유사 ash하지만 관리되는 옵션에만 적용되고 set관리되는 옵션에는 적용되지 않습니다 shopt.

sh1 Solaris의 POSIX는 /usr/xpg4/bin/sh(함수 로컬 옵션을 포함하여 많은 적합성 버그가 있지만)입니다. /bin/shSolaris 10 이전에는 Bourne 쉘(로컬 범위가 없음)이었고 Solaris 11 이후에는 ksh93입니다.

답변2

Stéphane의 답변에 대한 추가 정보를 얻으려면 하위 쉘을 사용하여 로컬을 얻으십시오.영향. 실제 POSIX 셸에 액세스할 수는 없지만 이는 busybox에서 작동합니다. 중괄호 대신 괄호를 사용하여 ash함수를 선언하세요 . 이렇게 하면 함수가 서브셸에서 실행됩니다.(){}

func() (
    echo "in func, before declaring: x=$x"
    x=10
    echo "in func, after declaring: x=$x"
)

x=5
echo "before func: x=$x"
func
echo "after func: x=$x"

산출

before func: x=5
in func, before declaring: x=5
in func, after declaring: x=10
after func: x=5

이는 함수가 전역 변수에 액세스할 수 있으며 함수 내에서 변수를 설정해도 전역 변수가 변경되지 않음을 나타냅니다. 나는 때때로 디렉토리를 변경하거나 변경하고 싶을 때 $IFS이 기술을 사용 cd하지만 이러한 작업이 프로그램의 나머지 부분에 영향을 미치는 것을 원하지 않습니다.

관련 정보