변수 선언 시 명령 대체 실행 방지

변수 선언 시 명령 대체 실행 방지

그래서 최근에 명령 대체를 사용하여 변수를 선언할 때 다음과 같이 말할 수 있다는 것을 알았습니다.

var=$(echo "this is running" > test; cat test)

그럼 그것~ 할 것이다실행(파일을 생성합니다 test). 아직 (기술적으로) 호출하지 않았지만 다음을 원합니다.

var=$(echo "this is running" > test; cat test)
echo "$var" # is where i would "normally" call the variable

변수에서 선언할 때 명령 대체가 실제로 실행되는 것을 방지하려면 어떻게 해야 합니까?달리기내가 그 변수를 호출하면?

추신: 이것이 나쁜 예라는 것은 분명하지만 "쓸모없는 고양이"와 "쓸모없는 메아리"에도 불구하고 내가 의미하는 바를 잘 보여줍니다...

답변1

내용이 동적으로 생성되는 변수를 원하는 것 같습니다.

bash지원하지 않음ksh93주제, 또는 zsh의동적으로 이름이 지정된 디렉터리또는 mksh가치 대체이렇게 하면 작업이 더 쉬워지지만 nameref를 사용하여 이 방법을 사용할 수 있습니다.

var_generator() { date --iso-8601=ns; }
var_history=()
typeset -n var='var_history[
  ${##${var_history[${#var_history[@]}]=$(var_generator)}},${#var_history[@]}-1
]'

여기서는 var배열 요소에 대한 참조로 정의되며 $var_history, 배열 인덱스가 동적으로 계산되고 임의의 코드를 실행할 수 있다는 점을 활용합니다(여기서는 함수를 실행 var_generator하고 해당 출력을 배열의 새 요소에 할당하는 데 사용됨).

그 다음에:

bash-5.1$ echo "$var"
2021-03-23T13:36:43,243211696+00:00
bash-5.1$ echo "$var"
2021-03-23T13:36:45,517726619+00:00

$(var_generator)여기서 사용할 수는 있지만 너무 복잡해 보입니다 . 하지만 한 가지 장점은 ${var#pattern}while bash(with zsh) will not let you do 와 같은 작업을 계속 수행할 수 있다는 것입니다 ${$(cmd)#pattern}.

답변2

실제로 호출했기 때문에 실행됩니다. 일반적으로 지연 평가되는 Make의 변수와는 달리 쉘 확장이 발생합니다. 이렇게 하면 var='$(...)'명령 대체가 실행되지 않지만 나중에 실행하기도 어려워집니다. 이는 foo=$bar나중에 최종적으로 사용될 때 값을 확인하는 것이 아니라 당시의 값을 복사하는 방식과 비슷합니다 .barfoo

간단한 대안은 함수를 사용하는 것입니다. 예를 들어, 다음은 약 5초 간격으로 두 개의 날짜를 인쇄해야 합니다.

getdate() {
    date +"%F %T"
}
a=$(getdate)
sleep 5
b=$(getdate)
echo "$a $b"

함수 사용의 단점은 매개변수 확장에 사용할 수 있는 문자열 작업을 사용할 수 없다는 것입니다. ${(getdate)% *}출력의 첫 번째 부분만 얻을 수는 없습니다 .foo=$(getdate); foo=${foo% *};

관련 정보