최근에 나는 bash 내장에 대해 더 많이 읽기로 결정했고 이로 인해 다음 declare
과 같은 결과를 얻었습니다.local
readonly
local variable_name
variable_name='value'
readonly variable_name
도착하다:
variable_name='value'
declare -r variable_name
이 변경으로 작성해야 할 줄 수가 줄어들고 변수 값이 정수임을 bash에 알리는 것과 같은 일부 속성을 설정할 수 있게 되었습니다. 그러나 cURL 별칭으로 사용할 함수를 만드는 동안 배열 내부의 변수는 사용하면 확장되지 않지만 declare
및 를 사용하면 잘 확장되는 것을 발견했습니다.local
readonly
예는 다음과 같습니다.
#!/usr/bin/env bash
set -o errexit -o errtrace -o pipefail -o nounset
IFS=$'\n\t'
curl() {
curl_version="$(command curl --version | awk 'NR==1 {print $2}')"
declare -r curl_version
curl_args=(
--user-agent "curl/${curl_version}"
--silent
--fail
)
command curl "${curl_args[@]}" \
"${@}"
}
curl --url 'https://httpbin.org/get'
변수가 어떤 이유로든 확장되지 않기 때문에 --user-agent
배열 부분은 bash가 아는 한 바인딩되지 않은 변수이고 set -o nounset
.
며칠 동안 작동시키려고 노력했기 때문에 이제 수건을 던지고 도움을 받아야 할 때라고 생각했습니다. 내가 뭘 잘못하고 있는지 올바른 방향으로 알려줄 수 있는 사람이 있나요?
편집하다:
언급하는 것을 잊어버렸지만, 예를 들어 같은 줄에 변수를 선언하면 declare -r variable_name
문제가 발생합니다.쉘체크 SC2155, 그래서 값을 설정한 후 선언하려고 합니다.
답변1
그리고:
curl_version="$(command curl --version | awk 'NR==1 {print $2}')" declare -r curl_version
함수에서 $curl_version
전역 변수를 일부 값으로 설정한 다음 처음에 설정되지 않은 별도의 로컬 읽기 전용 변수를 만듭니다.
당신이 원하는 것 같습니다 :
# instantiate a new local variable (but in bash it inherits the "export"
# attribute if any of the variable with same name in the parent scope)
local curl_version
# unset to remove that export attribute if any. Though you could
# also change the above to local +x curl_version
unset -v curl_version
# give a value:
curl_version="$(command curl --version | awk 'NR==1 {print $2}')"
# make that local variable read only
local -r curl_version
( 변수를 로컬로 만들고 싶다는 점을 더 명확하게 하기 local
위해 여기서는 not을 사용했습니다 .)declare
또는 동시에 모든 작업을 수행합니다.
local +x -r curl_version="$(command curl --version | awk '{print $2; exit}')"
(shellcheck가 지적한 것처럼, 그러면 파이프²의 종료 상태가 손실됩니다.)
어쨌든 저는 C에서와 같이 셸에서 /를 사용하지 않을 것입니다. readonly
특히 셸(ksh93 제외)에는 C와 같은 정적 범위가 없기 때문입니다. 그리고 (인스턴스와 반대로) 전역 범위에서 읽기 전용으로 설정된 경우 함수의 로컬 변수를 만들 수 없습니다.typeset -r
const
bash
bash
zsh
예를 들어:
count() {
local n
for (( n = 0; n < $1; n++ )) { echo "$n"; }
}
readonly n=5
count "$n"
zsh에서는 작동하지만 bash에서는 작동하지 않습니다. 그냥 사용 하고 절대 사용하지 않으면 local -r
괜찮을 것입니다 readonly
.
어쨌든 typeset
// declare
에서는 local
동일합니다 bash
. 유일한 차이점은 local
함수 외부에서 사용하려고 하면 오류를 보고한다는 것입니다. typeset -r
및 사이의 차이점( readonly
및 사이와 동일)은 함수 내에서 호출되는 경우 후자가 새 변수를 인스턴스화하지 않는다는 것입니다.typeset -x
export
² exit
해당 버전에서 SIGPIPE로 종료할 수 있는 첫 번째 줄 이후 입력 처리를 중지하는 방법을 확인하세요(출력이 한 번 전송되고 파이프에 맞기 때문에 실제로는 불가능함). 그 이후로 파이프는 결국 141 종료로 실패할 수 있습니다. 상태이지만 변수에 값을 할당할 수 있는 한 자체적으로는 여전히 성공합니다.awk
awk
curl
curl
pipefail
local
답변2
함수의 첫 번째 줄은글로벌바꾸다.
curl_version="$(command curl --version | awk 'NR==1 {print $2}')"
함수의 두 번째 줄은읽기 전용, 비어 있음, 로컬바꾸다
declare -r curl_version
이 지역 변수는 전역 변수의 값을 대체합니다.
다음 발췌 내용을 참고하세요 help declare
.
함수 내에서 사용될 때 "declare"는 "local" 명령을 사용하는 것처럼 이름을 로컬로 만듭니다. '-g' 옵션은 이 동작을 억제합니다.
나는 이것을 추천한다:
curl() {
local -r curl_version="$(command curl --version | awk 'NR==1 {print $2}')"
local curl_args=(
--user-agent "curl/${curl_version}"
--silent
--fail
)
command curl "${curl_args[@]}" \
"${@}"
}
변수를 확인하려면 declare -p curl_version curl_args
명령 호출 전에 함수에 변수를 추가하세요.