Bash의 echo가 독립 변수의 내용을 수정하는 이유는 무엇입니까?

Bash의 echo가 독립 변수의 내용을 수정하는 이유는 무엇입니까?

다음 코드가 있습니다(최소한의 예).

#!/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. 이는 허용되지 않습니다. 여기서 무슨 일이 일어나고 있나요?

  1. 첫 번째가 echo호출되어 한 줄을 인쇄 "# Foo Bar Baz Hello World \r"하고 즉시 다음 문자 \r(여기서는 공백)로 덮어씁니다.
  2. var으로 설정되어 있습니다 ''.
  3. 기능이 fun생성되었습니다.
  4. fun호출되어 다음과 var같이 설정됩니다.'something else'
  5. 이제 중요한 점이 있습니다. 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<

관련 정보