![Bash의 echo가 독립 변수의 내용을 수정하는 이유는 무엇입니까?](https://linux55.com/image/204941/Bash%EC%9D%98%20echo%EA%B0%80%20%EB%8F%85%EB%A6%BD%20%EB%B3%80%EC%88%98%EC%9D%98%20%EB%82%B4%EC%9A%A9%EC%9D%84%20%EC%88%98%EC%A0%95%ED%95%98%EB%8A%94%20%EC%9D%B4%EC%9C%A0%EB%8A%94%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
다음 코드가 있습니다(최소한의 예).
#!/bin/bash
echo -ne "# Foo Bar Baz Hello World \r "
var=''
function fun {
# some stuff happening in between
var='something else'
}
fun
echo $var
놀랍게도 출력은 다음과 같습니다.
$ /tmp/test.sh
something else
위의 에코가 변수의 내용을 수정할 수 있는 이유를 누군가 설명할 수 있습니까?
답변1
echo
위 스크립트의 내용은아니요변수를 수정합니다 var
. 이는 허용되지 않습니다. 여기서 무슨 일이 일어나고 있나요?
- 첫 번째가
echo
호출되어 한 줄을 인쇄"# Foo Bar Baz Hello World \r"
하고 즉시 다음 문자\r
(여기서는 공백)로 덮어씁니다. var
으로 설정되어 있습니다''
.- 기능이
fun
생성되었습니다. fun
호출되어 다음과var
같이 설정됩니다.'something else'
- 이제 중요한 점이 있습니다.
echo -n
개행 문자가 인쇄되지 않기 때문에 의 출력은var
길이에 도달할 때까지 위의 후행 문자 뒤의 문자를 덮어씁니다.var
이러한 동작으로 인해 입력의 세 부분( "# Foo Bar Baz Hello World"
, 및 ) " "
의 내용이 모두 'something else'
서로 겹쳐서 전체가 엉망이 됩니다.
이 탱글의 출력은 스크립트에 의해 "통과"됩니다(그리고 불쾌한 부작용을 일으킬 수 있습니다).
더 명확하게 설명하려면:
#!/bin/bash
echo -ne "# Foo Bar Baz Hello World \r ANYTHING"
var=''
function fun {
var=D
}
fun
echo $var
산출:
$ /tmp/test.sh
ANYTHINGDaz Hello World
그 결과 우리는 다음과 같은 사실을 배웠습니다.
echo -ne "Something \r"
echo
뒤에 공백만 있고 스크립트 출력이 잘린 경우 반환 값과 함께 사용할 수 있지만 \r
이전 문자열 \r
길이가 다음보다 작은 경우에만 가능합니다 var
.
=>피하세요.
답변2
운영자가 함수가 기본 프로그램의 변수를 수정할 수 있는 이유를 정말로 알고 싶다면 범위 지정과 관련이 있습니다. 기본적으로 모든 변수의 범위는 전역이며 함수 내부와 외부 모두에서 쓰고 읽을 수 있습니다. 즉, 함수는 하위 쉘이 아닌 호출 프로그램과 동일한 쉘에서 실행됩니다.
그러나 변수는 함수에 대해 로컬로 선언될 수 있으며, 이 경우 해당 변수는 해당 변수를 생성한 함수(및 호출하는 모든 함수) 내에서만 표시되며 종료 시 소멸됩니다.
서브셸이 생성되면 변수가 환경에 배치되며 서브셸 내에서는 변경할 수 없습니다. 덮어쓰는 경우 하위 쉘에 변수를 생성하여 완료되며 종료 시 이 변수는 손실됩니다.
고려하다:
#!/bin/bash
var=''
var2=''
echo ">$var<>$var2<"
function fun {
# some stuff happening in between
var='something else'
local var2='local'
}
fun
echo ">$var<>$var2<"
(
echo ">$var<"
var='level'
echo ">$var<"
)
echo ">$var<"
먼저 두 개의 변수를 만들고 그것이 무엇인지 확인하십시오. 다음으로 함수를 만들고 "something else"를 전역 변수에 할당하고 "local"을 포함하는 지역 변수를 만듭니다. 이 함수를 호출하세요. 이제 전역 변수는 설정되었지만 로컬 변수는 설정되지 않았습니다.
비교를 위해 마지막 부분은 먼저 환경의 변수를 에코하고 설정한 후 에코합니다. 그러나 서브쉘에서 복귀하면 변경사항이 손실됩니다.
$ ./X
><><
>something else<><
>something else<
>level<
>something else<