bash 함수는 다른 언어처럼 매개변수를 허용합니까?

bash 함수는 다른 언어처럼 매개변수를 허용합니까?

$PATH다음과 같이 설정할 수 있는 bash 기능이 있습니다 .

assign-path()
{
    str=$1
    # if the $PATH is empty, assign it directly.
    if [ -z $PATH ]; then
        PATH=$str;
    # if the $PATH does not contain the substring, append it with ':'.
    elif [[ $PATH != *$str* ]]; then
        PATH=$PATH:$str;
    fi
}

하지만 문제는 다른 변수에 대해 다른 함수를 작성해야 한다는 것입니다(예: $CLASSPATH유사한 함수에 대해 다른 함수를 작성하는 assign-classpath()등). 참조로 액세스할 수 있도록 bash 함수에 매개 변수를 전달하는 방법을 찾을 수 없습니다.

비슷한 게 있으면 더 좋을 것 같아요 -

assign( bigstr, substr )
{
    if [ -z bigstr ]; then
        bigstr=substr;
    elif [[ bigstr != *str* ]]; then
        bigstr=bigstr:substr;
    fi
}

bash에서 위와 같은 것을 구현하는 방법을 아시나요?

답변1

bash이를 사용하여 ${!varname}다른 변수가 참조하는 내용을 확장 할 수 있습니다. 예를 들어:

$ var=hello
$ foo () { echo "${!1}"; }
$ foo var
hello

매뉴얼 페이지에서:

${!prefix*}
${!prefix@}
       Names matching prefix.  Expands to the names of variables whose names
       begin with prefix, separated by the first character of the IFS special
       variable.  When @ is used  and the expansion appears within double quotes,
       each variable name expands to a separate word.

또는 참조된 변수의 내용을 설정하려면(위험 없음 eval) 을 사용할 수 있습니다 declare. 예를 들어:

$ var=target
$ declare "$var=hello"
$ echo "$target"
hello

따라서 다음과 같은 함수를 작성할 수 있습니다( declare함수 내에서 사용하는 경우 함수를 제공해야 하므로 주의하세요 -g. 그렇지 않으면 변수가 로컬이 됩니다).

shopt -s extglob

assign()
{
  target=$1
  bigstr=${!1}
  substr=$2

  if [ -z "$bigstr" ]; then
    declare -g -- "$target=$substr"
  elif [[ $bigstr != @(|*:)$substr@(|:*) ]]; then
    declare -g -- "$target=$bigstr:$substr"
  fi
}

다음과 같이 사용하세요.

assign PATH /path/to/binaries

substrif 가 이미 콜론으로 구분된 멤버 중 하나의 하위 문자열 bigstr이지만 자체 멤버가 아닌 경우 추가되지 않는 버그도 수정했습니다 . 예를 들어, 이미 포함된 /bin에 추가할 수 있습니다 . 이는 문자열이나 콜론의 시작/끝 및 기타 항목을 일치시키기 위해 세트를 사용합니다. 그렇지 않은 경우 대안은 다음과 같습니다.PATH/usr/binextglobextglob

[[ $bigstr != $substr && $bigstr != *:$substr &&
   $bigstr != $substr:* && $bigstr != *:$substr:* ]]

답변2

Bash 4.3의 새로운 기능은 & -n옵션입니다.declarelocal

func() {
    local -n ref="$1"
    ref="hello, world"
}

var='goodbye world'
func var
echo "$var"

출력되는 것은 입니다 hello, world.

답변3

매개변수를 설정하는 데 사용할 수 있습니다 eval. 이 명령에 대한 지침은 다음에서 찾을 수 있습니다.여기. 다음 사용법은 eval올바르지 않습니다.

잘못된(){
  평가$1=$2
}

추가 평가에 대해서는 eval다음을 사용해야 합니다.

분배하다(){
  평가$1='$2'
}

다음 기능을 사용한 결과를 확인하십시오.

$X1='$X2'
$X2='$X3'
$X3='xxx'
$
$에코:$X1:
:$X2:
$에코:$X2:
:$X3:
$에코:$X3:
:트리플 엑스:
$
$ 오류Y $X1
$에코:$Y:
:$X3:
$
$ 할당 Y $X1
$에코:$Y:
:$X2:
$
$ Y "hello world" 할당
$에코:$Y:
:안녕하세요 세계:
$#다음 내용은 예상치 못한 내용일 수 있습니다.
$ 할당Z $Y
$echo ":$Z:"
:안녕하세요:
$ # 따라서 두 번째 매개변수가 변수인 경우 따옴표로 묶어야 합니다.
$ 할당Z "$Y"
$echo ":$Z:"
:안녕하세요 세계:

하지만 그것을 사용하지 않고도 목표를 달성할 수 있습니다 eval. 나는 이 간단한 방법을 선호한다.

다음 함수는 올바른 방식으로 대체를 수행합니다. (희망합니다)

증가하다(){
  지역 전류=$1
  로컬 증분=$2
  지역의 새로운
  if [[ -z $CURRENT ]];
    새로운=$향상됨
  엘리프[[! ( ( $CURRENT = $AUGMENT ) || ( $CURRENT = $AUGMENT:* ) || \
    ( $current = *:$AUGMENT ) || ( $current = *:$AUGMENT:* ) ) ]];그러면
    신규=$현재:$향상됨
  기타
    새로운=$현재
    필리핀 제도
  에코 "$새"
}

다음 출력을 확인하십시오.

확장 /usr/bin /bin
/usr/bin:/bin

확장 /usr/bin:/bin /bin
/usr/bin:/bin

확장 /usr/bin:/bin:/usr/local/bin /bin
/usr/bin:/bin:/usr/local/bin

/bin:/usr/bin /bin 강화
/bin:/usr/bin

/bin /bin 강화
/쓰레기통


/usr/bin 확장: /bin
/usr/bin::/bin

확장 /usr/bin:/bin: /bin
/usr/bin:/bin:

/usr/bin:/bin:/usr/local/bin:/bin을 확장합니다.
/usr/bin:/bin:/usr/local/bin:

/bin:/usr/bin: /bin 강화
/bin:/usr/bin:

/bin 강화: /bin
/쓰레기통:


향상:/bin
::/쓰레기통


"/usr lib" "/usr bin"을 확장합니다.
/usrlib:/usrbin

"/usr lib:/usr bin" "/usr bin"을 확장합니다.
/usrlib:/usrbin

이제 augment이 함수를 사용하여 다음과 같은 방법으로 변수를 설정할 수 있습니다.

PATH=`PATH /bin 확장`
CLASSPATH=`CLASSPATH /bin 추가`
LD_LIBRARY_PATH=`확장 LD_LIBRARY_PATH /usr/lib`

답변4

assign () 
{ 
    if [ -z ${!1} ]; then
        eval $1=$2
    else
        if [[ ${!1} != *$2* ]]; then
            eval $1=${!1}:$2
        fi
    fi
}

$ echo =$x=
==
$ assign x y
$ echo =$x=
=y=
$ assign x y
$ echo =$x=
=y=
$ assign x z
$ echo =$x=
=y:z=

이것이 적절한가?

관련 정보