![Bash의 "문"이란 무엇입니까?](https://linux55.com/image/151181/Bash%EC%9D%98%20%22%EB%AC%B8%22%EC%9D%B4%EB%9E%80%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
일까츄 님의 답변을 읽은 후이 문제declare
내장된(매개변수 포함) 쉘의 존재 에 대해 배웠습니다 .-n
help declare
가져오다:
변수 값과 속성을 설정합니다.
변수를 선언하고 속성을 할당합니다. 이름을 지정하지 않으면 모든 변수의 속성과 값이 표시됩니다.
-n ... NAME을 값의 이름이 지정된 변수에 대한 참조로 만듭니다.
변수가 무엇인지, 확장하는지 잘 모르겠어서 declare
예제 와 함께 일반적인 설명을 요청했습니다 . 하지만 여전히 (변수 속성?) 을 놓치고 있습니다.man
man
declare
답변에 있는 ilkkachu의 코드를 기반으로 이것을 설명하고 싶을 수도 있습니다.
#!/bin/bash
function read_and_verify {
read -p "Please enter value for '$1': " tmp1
read -p "Please repeat the value to verify: " tmp2
if [ "$tmp1" != "$tmp2" ]; then
echo "Values unmatched. Please try again."; return 2
else
declare -n ref="$1"
ref=$tmp1
fi
}
답변1
대부분의 경우 암시적 선언으로 충분합니다.bash
asdf="some text"
그러나 때로는 변수의 값이 정수만 되기를 원할 수도 있습니다. 따라서 나중에 자동으로 변경하더라도 정수로만 변경될 수 있으며 경우에 따라 기본값은 0이 됩니다. 다음을 사용할 수 있습니다.
declare -i num
또는
declare -i num=15
때로는 배열이 필요하고 그 다음에는 필요합니다.declare
declare -a asdf # indexed type
또는
declare -A asdf # associative type
bash
예를 들어, 검색 문자열 "bash arraytutorial"(따옴표 제외)을 사용하여 인터넷을 탐색할 때 배열에 대한 훌륭한 튜토리얼을 찾을 수 있습니다.
linuxconfig.org/how-to-use-arrays-in-bash-script
변수를 선언할 때 가장 흔히 발생하는 경우인 것 같아요.
또한 참고하시기 바랍니다
- 함수에서
declare
변수를 로컬로 만듭니다(함수 내에서). 이름이 없으면 모든 변수가 나열됩니다(활성 쉘에 있음).
declare
declare
마지막으로 다음을 사용하여 bash
셸의 내장 명령 기능에 대한 간략한 요약을 얻을 수 있습니다.
help declare
답변2
출력은 help declare
매우 간결합니다. 더 명확한 설명은 man bash
or에서 찾을 수 있습니다 info bash
. 후자는 다음에 나오는 내용의 소스입니다.
첫째, 몇 가지 정의입니다. ~에 대한변수 및 속성:
ㅏ범위값을 저장하는 엔터티입니다. ...ㅏ바꾸다로 표시되는 매개변수입니다
name
. 변수에는값그리고 0개 이상속성. 내장 명령을 사용하여 속성 할당declare
...
또한 약declare
내장:
declare
declare [-aAfFgilnrtux] [-p] [name[=value] …]
변수를 선언하고 속성을 할당합니다. 이름이 지정되지 않으면 변수 값이 표시됩니다.
...
-n
각자에게이름이것이름 참조속성을 다른 변수에 대한 이름 참조로 만듭니다. 이 다른 변수는 다음 값으로 정의됩니다.이름. 모든 참조, 할당 및 속성 수정이름, 속성 자체를 사용하거나 변경하는 작업을 제외하고는 다음-n
에서 참조하는 변수에 대해 수행됩니다.이름값. ...
알아채다이름 참조변수는 Bash 4.3 이상1에서만 사용할 수 있습니다 .
또한 declare
Bash의 변수 속성에 대한 유용한 소개를 위해 다음을 알려드립니다.이 답변"무엇을 해야 declare name
하고 declare -g
무엇을 해야 할까요?"(주로 변수의 범위에 중점을 둡니다).
기본적으로 2 는 여러분 에게 친숙한 숙제 declare name=[value]
와 같습니다 . name=[value]
두 경우 모두 누락된 경우 name
null 값이 할당됩니다.value
declare name
약간 다르지만 그 반대는 아니라는 점에 유의하십시오 .놓다변수 name
3 :
$ declare name
## With the -p option, declare is used to display
## attributes and values of variables
$ declare -p name
declare -- name ## "name" exists
## Parameter expansion can be used to reveal if a variable is set:
## "isunset" is substituted to "name" only if unset
$ echo "${name-isunset}"
isunset
따라서 변수는 다음 name
과 같습니다.
- 발표하다그리고설정되지 않음, 뒤쪽에
declare name
; - 발표하다그리고놓다그리고유효하지 않은값으로
name=
또는 이후declare name=
; - 발표하다,놓다그리고비어 있지 않음
name=value
또는 그 이후의 값declare name=value
.
더 일반적으로,declare [options] name=value
- 변수 생성 - 이것은 이름이 있는 매개변수이며 정보를
name
저장하는 데 사용할 수 있는 메모리의 일부일 뿐입니다4 ; - 그것에 값을 할당하십시오
value
; name
선택적 으로 저장할 수 있는 값 유형을 정의하는 속성을 설정합니다 .유형, 엄밀히 말하면 Bash의 언어는 입력되지 않았기 때문에) 및 작동 방식입니다.
예를 들어 속성을 설명하는 것이 더 쉬울 수 있습니다. 을 사용하면 declare -i name
"정수" 속성 name
이 정수 참조로 처리되도록 설정됩니다.수동, "변수가 할당되면 산술 연산이 수행됩니다":
## Let's compare an ordinary variable with an integer
$ declare var
$ declare -i int
$ var="1+1"
$ int="1+1"
$ echo "$var"
1+1 ## The literal "1+1"
$ echo "$int"
2 ## The result of the evaluation of 1+1
위의 내용을 고려하면 ilkkachu의 코드에서 일어나는 일은 다음과 같습니다.
name이라는 변수를 선언하고
ref
"nameref" 속성을 설정한 후$1
(첫 번째 위치 인수)의 내용을 할당합니다.declare -n ref="$1"
이름 참조 변수의 목적
ref
은 일반적으로 사전에 알려지지 않은 다른 변수의 이름을 보유하는 것입니다. 아마도 동적으로 정의되기를 원하기 때문일 것입니다(예를 들어 코드 조각을 재사용하고 적용하기를 원하기 때문일 수 있음) 여러 변수)에 적용하고 이를 참조(및 조작)하는 편리한 방법을 제공합니다. (그러나 유일한 것은 아닙니다: 간접 참조가 대안입니다.쉘 매개변수 확장).변수의 값이
tmp1
할당되는 경우ref
:ref=$tmp1
ref
이름이 값인 추가 변수가 암시적으로 선언됩니다. 의tmp1
가치간접적으로에 대한 명시적 할당을 통해 암시적으로 선언된 변수에 할당합니다ref
.
그런 상황에서링크에 문제가 있습니다, 다음 read_and_verify
과 같이 호출됨
read_and_verify domain "Prompt text here..."
변수가 선언 domain
되고 값 tmp1
(즉, 사용자 입력)이 할당됩니다. 이는 사용자와 상호 작용하고 nameref 변수를 사용하여 선언하는 코드 domain
와 기타 변수를 재사용하도록 설계되었습니다.
암시적 부분을 자세히 살펴보기 위해 프로세스를 단계별로 재현할 수 있습니다.
## Assign a value to the first positional argument
$ set -- "domain"
## Declare the same "tmp1" variable as in your code
$ tmp1="value for domain"
## Declare a "ref" variable with the nameref attribute set and
## assign the value "domain" to it
$ declare -n ref="$1"
## Note that there is no "domain" variable yet
$ declare -p domain
bash: declare: domain: not found
## Assign a value to "ref" and, indirectly, to the "domain" variable
## that is implicitly declared
$ ref=$tmp1
## Verify that a variable named "domain" now exists, and that
## its value is that of "tmp1"
$ declare -p domain
declare -- domain="value for domain"
## Verify that "ref" is actually a reference to "domain"
$ domain="new value"
$ echo "$domain"
new value
$ declare -p ref
declare -n ref="domain"
$ echo "$ref"
new value
1참고자료 :다양성파일의 "3. Bash의 새로운 기능" 섹션에서 "w"를 클릭하세요.
이는 관련이 있을 수 있습니다. 예를 들어 CentOS Linux 7.6(현재 최신 버전)배쉬 4.2와 함께 제공.
2. 쉘 내장 기능과 동일, 상세그리고다양하고 이질적인 작업을 수행하기 때문에 간결한 설명은 어렵습니다. 저는 속성 선언, 할당 및 설정에만 중점을 두고 속성 나열, 범위 지정 및 삭제에 대해 고려할 것입니다. 이는 이 답변의 범위를 벗어납니다.
3 이 동작은 Bash 4.4에서 도입되었습니다 . 인용하다:declare -p
다양성파일의 "3. Bash의 새로운 기능" 섹션에서 "f"를 클릭하세요.
~처럼G-맨Bash 4.3에서 declare name; declare -p name
오류가 발생한다는 것이 주석에 언급되어 있습니다. 그러나 name
를 사용하여 존재 여부를 확인할 수 있습니다 declare -p | grep 'declare -- name'
.
4개의 완전한 Bash 가이드,매개변수mywiki.wooledge.org에서
답변3
이에 대해 설명하려고 노력하겠지만 제공하신 예를 따르지 않더라도 양해해 주시기 바랍니다. 오히려 나는 당신에게 나 자신의 다른 접근 방식을 안내하려고 노력하고 싶습니다.
"변수" 및 "확장"과 같은 개념을 이미 이해하고 있다고 말씀하셨으므로 몇 가지 배경 지식만 훑어보고 그렇지 않으면 좀 더 심층적인 초점이 필요합니다.
그래서 제가 가장 먼저 말씀드리고 싶은 것은 기껏해야기초적인수준에서 이 declare
명령은 Bash에게 변수 값(예: 스크립트 실행 중에 변경될 수 있는 값)을 원하고 특정 이름, 정확히 이름을 사용하여 해당 값을 참조할 것임을 알리는 방법일 뿐입니다. 명령 declare
자체 옆에 지정하십시오.
그건:
declare foo="bar"
Bash에게 이름이 지정된 변수 foo
에 값이 있기를 원한다고 알려주세요 bar
.
하지만..잠깐만요.. declare
사용하지 않고도 이 작업을 수행할 수 있습니다. 그렇죠? 좋다:
foo="bar"
매우 사실입니다.
글쎄요, 위의 간단한 할당이 실제로는절대적인사실 .. 변수를 선언하는 방법입니다.
(위와 같은 일이 발생했습니다.하나여러 가지 방법변화; 라는 변수의 값은 foo
실제로 가장 직접적이고, 간결하고, 분명하고, 간단한 방법입니다... 하지만 이것이 유일한 방법은 아닙니다... 이에 대해서는 나중에 다시 설명하겠습니다...).
그러나 "변수의 값을 표시할 이름"(이하에서는 간결하게 "변수"라고 함)을 사용하지 않고 선언하는 것이 전적으로 가능하다면 declare
왜 이 거창한 "선언" 명령을 사용하겠습니까?
대답은 변수( )를 선언하는 암시적인 방법에 있습니다 foo="bar"
. 이는... 암시적으로... Bash가 변수가 일반적인 쉘 사용 시나리오에서 가장 일반적으로 사용되는 유형이라고 생각하게 만듭니다.
이 유형은 특정 의미가 없는 일련의 문자인 문자열 유형입니다. 따라서 암시적 선언을 사용하면 문자열을 얻게 됩니다.
그러나 프로그래머는 때때로 변수를 숫자와 같이 처리해야 합니다. 변수에 대해 산술 연산을 수행해야 하며 다음과 같은 암시적 선언을 사용해야 합니다.foo=5+6
에 익숙해foo
Bash가 의도한 대로 값 11을 할당하도록 합니다. 오히려 foo
세 문자의 시퀀스 에 할당하는 것이 좋습니다 5
+
6
.
foo
따라서 .. 문자열이 아닌 숫자로 처리되기를 Bash에게 알리는 방법이 필요합니다 . 이는 명시적 기능이 declare
유용한 곳입니다.
말하다:
declare -i foo=5+6 # <<- note the '-i' option: it means 'integer'
Bash가 기꺼이 당신을 위해 계산을 하고 할당해 줄 것입니다.숫자변수에 대한 값은 11입니다 foo
.
즉, 변수를 declare -i foo
제공한다고 말함으로써foo
속성정수입니다.
숫자(Bash는 여전히 소수, 부동 소수점 숫자 등을 이해하지 못하기 때문에 정확한 정수)를 선언하는 것이 아마도 를 사용하는 첫 번째 이유일 것입니다 declare
. 그러나 그것이 유일한 이유는 아닙니다. 이미 알고 있듯이 변수에 다른 속성을 할당할 수도 있습니다. 예를 들어 Bash에게 무슨 일이 있어도 항상 변수 값을 대문자로 표시하도록 지시할 수 있습니다. 라고 말하면 declare -u foo
그 시점부터 foo=bar
Bash가 실제로 문자열을 BAR
변수에 할당한다고 말하면 됩니다 foo
.
이러한 속성을 변수에 할당하려면~ 해야 하다명령을 사용하십시오 declare
. 다른 옵션은 없습니다.
이제 제공할 수 있는 또 다른 속성 declare
은 악명 높은 "name-ref" 속성 -n
인 속성입니다. (이제는 예전에 치워두었던 컨셉을 다시 살리고 싶어요).
기본적으로 name-ref 속성은 Bash 프로그래머가 변수 값을 변경할 수 있는 또 다른 방법을 허용합니다. 더 정확하게 알려준다간접적인이를 수행하는 방법.
이것은어떻게효과가있다:
당신은 다음 과 같은 declare
속성을 가진 변수 입니다.-n
매우값도 지정하는 것이 좋습니다(엄격히 필수는 아니지만 작업이 더 쉬워짐).이것동일한 declare
명령에도 다양한 변형이 있습니다. 이와 같이:
declare -n baz="foo"
이는 Bash에게 그 이후로 이름이 지정된 변수의 값을 사용하거나 변경할 때마다 baz
실제로 이름이 지정된 변수의 값을 사용하거나 변경해야 한다는 것을 알려줍니다 foo
.
이는 그 시점부터 baz=10+3
make foo
get the value 13 과 같은 명령을 내릴 수 있음을 의미합니다. 물론 foo
이전에 정수( declare -i
)로 선언되었다고 가정하면, 그렇지 않으면 4개의 문자 시퀀스를 얻게 됩니다 1
0
+
3
.
foo
또한: 에서와 같이 값을 직접 변경 하면 foo=15
say 로 15도 표시됩니다 echo “${baz}”
. 이는 baz
name-ref로 선언된 변수는 foo
항상 foo
의 값을 반영하기 때문입니다 .
위의 declare -n
명령은 변수를 만들기 때문에 "이름 참조"라고 합니다.baz
인용하다도착하다이름또 다른 변수에요. 실제로 우리는 이 옵션 덕분에 Bash에서 다른 변수 이름으로 처리되는 baz
"foo" 값으로 선언했습니다.-n
지금,왜지구에서 이런 일을 하고 싶나요?
음..이것은 상당히 고급 요구 사항을 충족하는 기능이라는 점은 언급할 가치가 있습니다.
실제로 프로그래머가 실제로 이름 참조가 필요한 문제에 직면했을 때 그러한 문제를 해결하려면 Bash보다는 적절한 프로그래밍 언어를 사용해야 할 정도로 발전했습니다.
예를 들어, 이러한 높은 수준의 요구 사항 중 하나는 프로그래머로서 개발 중에 알 수 없는 경우입니다.어느스크립트의 특정 지점에서 변수를 사용해야 하지만~ 할 것이다런타임 시 동적으로 완전히 이해됩니다. 프로그래머가 런타임에 개입할 수 없다는 점을 고려하면 유일한 옵션은 프로비전을 만드는 것입니다. 전진스크립트의 이러한 상황에서는 아마도 "name-ref"가 유일한 방법일 것입니다. 이러한 고급 요구 사항에 대한 잘 알려진 사용 사례로 플러그인을 고려해보세요. "플러그형" 프로그램의 프로그래머는 향후(및 아마도 제3자) 플러그인에 대한 일반 규정을 미리 작성해야 합니다. 따라서 프로그래머는 Bash에서 name-ref와 같은 도구를 사용해야 합니다.
또 다른 고급 요구 사항은 대량의 데이터를 처리해야 하는 경우입니다.기억 속에 그리고또한 스크립트 함수에 해당 데이터를 전달해야 합니다.반품이 데이터는 도중에 수정되어야 합니다. 이 경우에는 물론 가능합니다.복사데이터는 한 함수에서 다른 함수로 전송되지만(Bash처럼 dest_var="${src_var}"
또는 에서와 같은 함수를 호출할 때 myfunc "${src_var}"
) 데이터가 커서 엄청난 RAM 낭비가 발생합니다.그리고매우 비효율적인 작업입니다. 따라서 이러한 상황이 발생하면 해결책은 데이터 사본을 사용하는 것이 아니라인용하다이 데이터에. Bash에서는 이름이 인용됩니다. 이 사용 사례는 실제로 모든 현대 프로그래밍 언어의 표준이지만 Bash에서는 매우 예외적입니다. Bash는 주로 파일 및 외부 명령을 주로 처리하는 짧고 간단한 스크립트용으로 설계되었기 때문에 Bash 스크립트는 엄청난 양의 코드를 전달할 필요가 매우 적습니다. 함수 간 데이터. 스크립트의 기능이 일부 데이터를 공유해야 하는 경우(액세스 및 수정) 이는 일반적으로 Bash 스크립트에서 흔히 사용되는 전역 변수를 사용하여 간단히 달성할 수 있습니다.매우해당 프로그래밍 언어에서는 더 이상 사용되지 않습니다.
그렇다면 Bash의 이름 참조에 대한 주목할만한 사용 사례가 있을 것입니다. 그리고 (아마 아이러니하게도) 이는 다른 유형의 변수로 작업할 때와 관련이 있습니다.
- "인덱스 배열"로 선언된 변수(
declare -a
) - "연관 배열"( )로 선언된 변수입니다
declare -A
.
이는 다음과 같은 변수 클래스입니다.더 쉽게(그리고 더 효율적으로) 많은 데이터를 전달하지 않더라도 일반 복사보다는 이름 참조를 사용하여 함수를 전달합니다.
이러한 모든 예제가 이상하게 들리고 여전히 이해하기 어렵다면 이는 이름 참조가 실제로 고급 주제이고 Bash의 일반적인 사용 시나리오에는 거의 필요하지 않기 때문입니다.
Bash에서 이름 참조의 용도를 찾은 몇 가지 상황을 말씀드릴 수 있지만 지금까지는 대부분 상당히 "비교적"이고 복잡한 요구 사항에 사용되었습니다. 학습 중이세요. 이 단계에서는 상황이 복잡해질 수 있습니다. 가장 덜 복잡한(아마도 심오하지 않은) 것을 언급하자면, 함수에서 값을 반환하는 것입니다. Bash는 실제로 이것을 지원하지 않으므로 name-ref를 사용하여 동일한 기능을 얻었습니다. 그런데, 이것이 바로 예제 코드가 수행하는 작업입니다.
그 외에도 실제로 댓글에 더 적합할 작은 개인적인 제안이 있지만 StackExchange 댓글의 한계에 맞도록 충분히 압축할 수는 없습니다.
제 생각에는최대지금 해야 할 일은 제가 보여드린 간단한 예와 제공한 샘플 코드를 사용하여 name-ref를 시험해 보는 것입니다. 지금은 "정확히 왜" 부분을 무시하고 "작동 방식" 부분에만 약간의 실험을 가하는 것입니다. , "어떻게" 부분 " 부분이 마음에 더 잘 자리잡을 수 있으므로 "왜" 부분은 적절한 과정에서 실제 실제 문제에 직면할 때(또는 경우) 그 이름이 — — 심판이 나오는 경우에 명확해집니다. 능숙한.
답변4
Declare는 Bash에서 변수를 선언하는 여러 구문 중 하나입니다.
x=7
declare x=7
declare x
function something {
local x
local x=7
}
변수를 선언하는 이러한 다양한 방법은 쉘이 점진적으로 발전한 결과입니다.
이는 -n
때때로 "변수"라고 불리는 것을 선언하는 방법입니다. 이는 다른 변수에 바인딩된 변수입니다. 다음 스크립트를 테스트할 수 있습니다.온라인:
#!/bin/bash
set -o errexit -o nounset -o pipefail
declare thevariable
declare -n thevariablevariable=thevariable
thevariable='the value'
printf 'thevariable: %s\n' "$thevariable"
printf 'thevariablevariable: %s\n' "$thevariablevariable"
thevariablevariable='the other value'
printf 'thevariable: %s\n' "$thevariable"
printf 'thevariablevariable: %s\n' "$thevariablevariable"
이를 실행하면 thevariablevariable
에 대한 포인터 thevariable
가 아니라 별칭이 표시됩니다 thevariable
.
thevariable: the value
thevariablevariable: the value
thevariable: the other value
thevariablevariable: the other value
자, 이것은 교활한 버그 기능처럼 보일 수도 있지만 실제로는 특이한 언어 기능입니다. 그러나 쉘 프로그래밍에는 때때로 이상한 기능이 필요합니다.
쉘은 이론적으로 매우 단순하고 Lofi 언어이기 때문에 쉘에서 변수를 선언하는 방법이 너무 많다는 것이 이상해 보이지만 이는 프로그래밍 방식의 점진적인 변화와 관련이 있습니다. 예제는 함수 지역 변수 정의입니다.
값을 설정하는 가장 간단한 방법은 분명히 입니다 x=7
. 그러나 함수가 있는 스크립트가 있을 때 다음은 무엇을 의미합니까?
#!/bin/bash
set -o errexit -o nounset -o pipefail
x=7
function something {
x=6
}
something
printf 'What is x? It is: %s\n' "$x"
글쎄요, 한 가지 합리적인 설명은 x
여전히 스크립트 끝에 있어야 한다는 것입니다 7
. 그러나 실제로는 6입니다. 왜냐하면 함수 선언이 로컬이라는 것이 프로그래머들 사이에서 일반적인 기대가 아니었던 때가 있었기 때문입니다. 경험에 따르면 로컬 함수는 좋은 습관이지만 셸에서 선언의 의미를 단순히 변경할 수는 없습니다. 이렇게 하면 모든 이전 스크립트가 손상되기 때문입니다. 따라서 새로운 선언 구문을 도입합니다.