소스 bash 스크립트에서 변수를 로컬로 만드는 가장 좋은 방법은 무엇입니까?

소스 bash 스크립트에서 변수를 로컬로 만드는 가장 좋은 방법은 무엇입니까?

내 컴퓨터에서 일부 장기 실행 작업에 대한 진행 보고서를 생성하는 bash 스크립트가 있습니다. 기본적으로 이 상위 스크립트는 하위 스크립트 목록을 반복합니다(호출 포함 source). 하위 스크립트는 상위 스크립트에서 사용할 몇 가지 특정 변수를 설정해야 합니다.

오늘 저는 첫 번째 첨자로 설정된 변수가 실수로 두 번째 첨자에서 사용되어 잘못된 출력이 발생하는 버그를 발견했습니다. 이러한 유형의 오류가 발생하지 않도록 방지할 수 있는 확실한 방법이 있습니까?

기본적으로, 제가 source하위 스크립트일 때 일부 특정 변수를 상위 스크립트에 다시 유지하고 싶습니다. 내 상위 스크립트는 각각의 새로운 하위 스크립트 전에 이러한 특정 변수를 재설정하므로 source문제가 없습니다. 그러나 일부 하위 스크립트에는 상위 스크립트에 다시 유지되어서는 안되는 로컬로 사용되는 추가 임의 변수가 있을 수 있습니다.

분명히 아래 첨자의 끝에서 이들 각각을 수동으로 설정 해제할 수 있지만, 이들 중 하나를 잊어버리면 오류가 발생하기 쉬운 것 같습니다. 스크립트를 가져오고 특정 변수만 호출된 스크립트에 유지하는 더 적절한 방법이 있습니까 source?

편집: 명확성을 위해 상위 스크립트의 단순화된 버전은 다음과 같습니다.

echo "<html><body><h1>My jobs</h1>"

FILES=~/confs/*.sh
for f in $FILES; do
  # reset variables
  name="Unnamed job"
  secsSinceActive="Unknown"
  statusText="Unknown"

  # run the script that checks on the job
  source "$f"

  # print bit of report
  echo "<h3>$name</h3>"
  echo "<p>Last active: $secsSinceActive seconds ago</p>"
  echo "<p>Status: $statusText</p>"

echo "</body></html>"

아래 첨자 중 하나는 다음과 같습니다.

name="My awesome job"

nowTime=`expr $(date +%s) `
lastActiveTime=`expr $(date +%s -r ~/blah.log)`
secsSinceActive=`expr $nowTime - $lastActiveTime`

currentRaw=$(cat ~/blah.log | grep "Progress" | tail -n 1)
if [ -z "$currentRaw" ]; then
  statusText="Not running"
else
  statusText="In progress"
fi

$name, $secsSinceActive 및 $statusText 변수는 상위 스크립트에 다시 유지되어야 하지만 다른 모든 변수는 하위 스크립트가 종료되면 사라져야 합니다.

답변1

함수로 가져오려는 전체 스크립트를 래핑하고 함수에서만 사용하려는 선언 앞에 local을 추가한 다음 스크립트 끝에서 함수를 호출합니다.

func () {
    local name="My awesome job"

    nowTime=`expr $(date +%s) `
    lastActiveTime=`expr $(date +%s -r ~/blah.log)`
    local secsSinceActive=`expr $nowTime - $lastActiveTime`

    currentRaw=$(cat ~/blah.log | grep "Progress" | tail -n 1)
    if [ -z "$currentRaw" ]; then
      local statusText="Not running"
    else
      local statusText="In progress"
    fi
}
func

답변2

전체 스크립트를 함수로 래핑하는 변형은 sourced 스크립트가 소스 코드 자체를 가져오도록 하는 것입니다.통과하다기능:

bleh.sh스크립트 를 source-ing 하자

#!/bin/bash

echo -e "\x1b[34mI am  $(basename ${BASH_SOURCE[0]})\x1b[0m"

source blah.sh

echo -e "\x1b[34mStill $(basename ${BASH_SOURCE[0]})\x1b[0m"

echo -e "\x1b[34mA=$A\x1b[0m"
echo -e "\x1b[34mB=$B\x1b[0m"

그리고 d blah.sh스크립트 source:

#!/bin/bash

echo -e "\x1b[33mI am  $(basename ${BASH_SOURCE[0]})\x1b[0m"

fun() {
    local A
    local HACK_ACTIVATED=yes
    source "$1"
}

(return 0 2>/dev/null) && [ -z "$HACK_ACTIVATED" ] && {
    fun "${BASH_SOURCE[0]}"
    return
}

echo -e "\x1b[33mStill $(basename ${BASH_SOURCE[0]})\x1b[0m"

A=1
export B=1
echo -e "\x1b[33mA=$A\x1b[0m"
echo -e "\x1b[33mB=$B\x1b[0m"

실행 시 bleh.sh출력은 다음과 같습니다.

여기에 이미지 설명을 입력하세요.

작동 방식:

  1. bleh소스 의 경우 아직 설정되지 않은 지역 변수 에서 알 수 있듯이 Ⓐ 획득되었으며 Ⓑ 아직 자체 획득되지 않았음을 확인 blah.sh하세요 .blah.shfun()fun()HACK_ACTIVATED
  2. blah.sh그런 다음 현재 스크립트를 호출하여 fun()함수에 전달합니다.
  3. fun()로컬로 유지하려는 변수를 로컬 변수로 설정한 다음재귀적으로 source해당 스크립트를 다시 포함합니다( blah.sh).

(소스인지 확인한 이유는 blah.sh제 경우에는 스크립트가 독립형으로도 작동하기 때문입니다.)

답변3

Bash에서 변수를 로컬로 만드는 구문은 다음과 같습니다.

local variable_name=

이것이 함수에서 작동한다는 것을 알고 있지만 여러 스크립트에서 어떻게 작동하는지 잘 모르겠습니다.

관련 정보