여러 항목이 포함된 각 배열의 경우

여러 항목이 포함된 각 배열의 경우

나는 물건을 다운로드하는 스크립트를 작성 중입니다.

스크립트에서 반복적으로 다운로드될 이름과 URL(따라서 스크립트)을 연결해야 합니다.

name1,url1
name2,url2
name3,url3


command $NAME $URL

그래서 나는 이름 목록과 해당 URL 목록을 반복하기 위해 모든 루프를 원합니다. 이를 달성하는 가장 좋은 방법은 무엇입니까? 현재는 이 목록을 외부 파일이나 다른 곳에 저장하는 데 관심이 없습니다. 대본에는 내가 원하는 것의 예가 있습니다.

답변1

bash이와 관련하여 매우 제한적입니다. 다른 쉘을 사용해 볼 수도 있습니다.

사용하십시오 ( 에서 변수를 인용하지 않았으므로 zsh이미 구문을 사용하고 있습니다 ).zshcommand $NAME $URL

for name url (
  name1 url1
  name2 url2
  name3 url3
) command $name $url

bashPOSIX 셸 또는 기타 POSIX 셸을 사용하면 다음을 수행할 수 있습니다.

while IFS=, read <&3 -r name url; do
  {
    command "$name" "$url"
  } 3<&-
done 3<< "EOF"
name1,url1
name2,url2
name3,url3
EOF

이는 값에 쉼표나 개행 문자를 포함할 수 없음을 의미합니다.

최신 버전은 bashksh93과 유사한 구문을 사용하여 연관 배열도 지원합니다 zsh. 따라서 이름이 고유한 경우 다음을 수행할 수 있습니다.

typeset -A pairs
pairs=(
  [name1]=url1
  [name2]=url2
  [name3]=url3
)
for name in "${!pairs[@]}"; do
  url=${pairs[$name]}
  command "$name" "$url"
done

이는 또한 적용됩니다 ksh93. 인용 규칙은 둘 사이에 약간 다릅니다. 에서는 zsh연관 배열 정의 구문이 더 간단하며 일반적인 인용 규칙이 적용됩니다.

pairs=(name1 url1 name2 url2 name3 url3)

다음과 같이 몇 줄로 입력할 수 있습니다.

pairs=(
  name1 url1
  name2 url2
  name3 url3
)

2021년 편집: 이제 ksh93 구문이 zsh지원되고 zsh 구문 도 지원됩니다 .hash=([key]=value)bashhash=(key value)

순서는 유지되지 않으며 bash연관 배열은 널 키를 지원하지 않습니다.

ksh93다차원 배열이 지원되므로 다음과 같이 할 수 있습니다.

pairs=((name1 url1) (name2 url2) (name3 url3))
for ((i = 0; i < ${#pairs[@]}; i++)); do
  name=${pairs[i][o]} url=${pairs[i][1]}
  command "$name" "$url"
done

execve()또는 NUL, 엄밀히 말하면 NUL은 시스템 호출을 통해 실행되는 명령 에 전달될 수 없지만이름섹션에는 쉼표를 포함할 수 없지만URL부분은 2개 이상이면 괜찮고, 1개만 있어도 끝이 아닙니다. 그 방식은 $IFS하나를 제외하고는 쉘에서 분할하는 것으로 해석되기 때문입니다 zsh.

답변2

여기 문서를 생성하여 임시 파일에 쓴 후 처리할 수 있습니다. 임시 파일은 자동으로 삭제되므로 수동으로 정리할 필요가 없습니다.

#!/bin/bash
mylist=/var/tmp/$$
trap 'rm -f ${mylist}' EXIT
cat << _EOF_ > ${mylist}
name1 url1
name2 url2
name3,url3
_EOF_
while read name url
do
    printf "%s %s\n" ${name} ${url}
done < ${mylist}

답변3

처음에는 연관 배열만큼 복잡한 것을 생각했습니다.
그런 다음 URL만큼 이름이 많다는 점을 고려하면 다음과 같이 간단하게 수행할 수 있다는 것을 깨달았습니다.

root@debian:a=( "name1,url1" "name2,url2" "name3,url3" );while IFS="," \ 
read -r name url;do echo "command $name $url";done<<<$(printf '%s\n' "${a[@]}")
command name1 url1
command name2 url2
command name3 url3

당신이 해야 할 일은 이름과 URL을 동일한 배열(내 테스트에서는 a)에 쉼표로 구분하여 저장하는 것뿐입니다.

답변4

아마도 간단한 bash 스크립트가 도움이 될 것입니다.

pairs=( "name1,url1" "name2,url2" "name3,url3" )

for pair in "${pairs[@]}"; do
    IFS=, read name url <<<"${pair}"
    printf "%s %s\n" "${name}" "${url}"
    command "${name}" "${url}"
done

관련 정보