다른 변수에 의해 이름이 유지되는 변수에 bash 배열을 복사합니다.

다른 변수에 의해 이름이 유지되는 변수에 bash 배열을 복사합니다.

비슷한 질문이 많이 있지만 다음 문제에 대한 해결책으로 답변을 이해할 수 없습니다.

두 개의 매개변수를 사용하는 bash 함수를 만들고 싶습니다. 첫 번째는 변수 이름이고 두 번째는 검색 문자열(파일 검색용)입니다.

그래서 변수 이름에 발견된 파일의 배열이 저장되기를 원합니다.

다음 파일이 포함된 디렉터리가 있습니다.

  • .jpg
  • b.tif
  • c.jpg

함수는 다음과 같이 정의됩니다.

search-files--fill-array()
{
    local variable_name="${1}"
    declare -a eval ${variable_name}

    local search_string="${2}"
    echo "${search_string}"

    local nullglob_setting=$(shopt -p nullglob)
    shopt -s nullglob
    found_files=(${search_string})
    eval "${nullglob_setting}"

    eval ${variable_name}=(${found_files[@]})
}

그러나 마지막 줄에서는 구문 오류가 발생합니다. 함수의 첫 번째 인수로 제공된 변수에 배열을 할당해야 하므로 함수가 호출됩니다.

search-files--fill-array my_variable_a "*.jpg"

따라서 원하는 결과는 다음과 같아야 합니다.

echo "${my_variable_a[@]}"

두 개의 파일 "a.jpg"와 "c.jpg"를 배열로 표시합니다. 즉,

echo "${#my_variable_a[@]}"

결과는 "2"여야 합니다.

배열일 필요가 없는 경우 해결책은 다음 마지막 줄을 사용하는 것입니다.

eval ${variable_name}=\${found_files}

성공하지 못한 채 while 루프를 사용하여 이전 배열에서 새 배열을 형성하려고 시도했지만 그 역시 작동하지 않았습니다.

eval ${variable_name}="\${found_files[@]}"

my_variable_a문자열은 포함하지만 배열은 포함하지 않는 결과를 생성합니다 .

배경

어쩌면 내가 완전히 잘못하고 있는 것일 수도 있습니다.

명확하게 말하면, 와일드카드를 통해 찾은 파일의 파일 이름을 각각 보유하는 일부 변수로 배열을 채우고 싶습니다(항상 다른 검색 "문자열"에 대해 동일한 방식). 하위 디렉터리가 아닌 파일만 예상하고 결과가 항상 안정적으로 정렬되도록 해야 합니다. )

중복되는 코드를 피하고 싶습니다.

shopt부분은 파일이 현재 디렉터리에 없는 경우 배열이 0개의 항목으로 채워지고, nullglob이 없는 경우 "문자열"로 검색된 콘텐츠가 포함된 항목이 하나 있는지 확인하는 데 필요합니다.

해결책

~처럼빌리 삼촌여기서 사용할 수 있는 제안입니다 declare -n var.

작업 기능:

search-files--fill-array()
{
    declare -n function=$1
    local shopt_setting=$BASHOPTS
    shopt -s nullglob
    function=($2)
    [[ :$shopt_setting: = *:nullglob:* ]] || shopt -u nullglob
}

그가 제안한 재설정 프로세스로 nullglob인해 해당 기능은 더 이상 어떤 기능도 포함하지 않게 됩니다 eval. 예를 들어 읽을 수 있습니다.이 스택 교환 게시물회피를 eval고려해 볼 가치가 있는 이유를 알아보세요.

답변1

변수 참조를 사용하십시오.

search-files--fill-array()
{
  typeset -n a=$1
  local s=$BASHOPTS
  shopt -s nullglob
  a=($2)
  [[ :$s: = *:nullglob:* ]] || shopt -u nullglob
}

prompt> touch foo.txt bar.txt
prompt> search-files--fill-array foo '*.txt'
prompt> typeset -p foo
declare -a foo=([0]="bar.txt" [1]="foo.txt")

help declare자세한 내용을 알아보세요( declare예의 동의어 typeset).


declare -a eval ${variable_name}

그러면 두 개의 배열이 선언됩니다.현지의함수의 경우 하나는 이름이 지정 eval되고 다른 하나는 content 로 이름이 지정됩니다 ${variable_name}. 할당한 값은 함수가 반환된 후에 손실됩니다. declare -g그들을 세계화하기 위해 .

eval ${variable_name}=(${found_files[@]})=> 구문 오류

echo foo=(bar)=> 구문 오류와 동일합니다. (명령 시작 부분(예: 이후 등)이나 배열에 할당할 때 사용되는 특수 구문의 일부 외에는 어디에서나 사용할 수 없는 메타 문자 ;입니다 &&.

관련 정보