bash에서 튜플을 반복 할 수 있습니까?
예를 들어 다음이 작동하면 좋을 것입니다.
for (i,j) in ((c,3), (e,5)); do echo "$i and $j"; done
어떻게 든 튜플을 반복 할 수있는 해결 방법이 있습니까?
bash에서 튜플을 반복 할 수 있습니까?
예를 들어 다음이 작동하면 좋을 것입니다.
for (i,j) in ((c,3), (e,5)); do echo "$i and $j"; done
어떻게 든 튜플을 반복 할 수있는 해결 방법이 있습니까?
답변:
$ for i in c,3 e,5; do IFS=","; set -- $i; echo $1 and $2; done
c and 3
e and 5
set
(부터 man builtins
) 사용에 대해 :
옵션 처리 후에 남아있는 모든 인수는 위치 매개 변수의 값으로 처리되며 순서대로 $ 1, $ 2, ... $ n에 지정됩니다.
는 IFS=","
모든 그래서 필드 분리 세트 $i
로 분할 도착 $1
하고 $2
정확하게한다.
이 블로그를 통해 .
편집 : @SLACEDIAMOND가 제안한 더 정확한 버전 :
$ OLDIFS=$IFS; IFS=','; for i in c,3 e,5; do set -- $i; echo $1 and $2; done; IFS=$OLDIFS
c and 3
e and 5
IFS
좋습니다. 명령 줄에서 실행하면 저장하고 원래 값으로 재설정해야한다는 점을 지적하고 싶습니다 . 또한 새로운 IFS
것은 매 반복이 아니라 루프가 실행되기 전에 한 번 설정할 수 있습니다.
set -- $i
IFS
다음 set
명령에 대해서만 설정하십시오 for i in c,3 e,5; do IFS="," set -- $i; echo $1 and $2; done
. 답변을 수정하십시오. 모든 독자가 나열된 솔루션 중 하나만 선택한다면 전체 개발 기록을 읽어야하는 것은 의미가 없습니다. 이 멋진 트릭에 감사드립니다!
tuples="a,1 b,2 c,3"
하고 IFS=','
편집 된 버전으로 넣으면 c,3 e,5
사용 $tuples
하는 대신 전혀 잘 인쇄되지 않습니다. 그러나 대신 for 루프에서 키워드 IFS=','
바로 뒤에 넣으면 리터럴 값뿐만 do
아니라 사용할 때도 잘 작동 $tuples
합니다. 말할만한 가치가 있다고 생각했습니다.
IFS
반복을 분할하는 데 사용 하기 때문 입니다. 이 같은 배열을 통해 루프 경우 즉 arr=("c,3" "e,5")
넣어 IFS
루프에 대한 이전의 값은 $i
단지 것입니다 c
그리고 e
, 그것은 멀리 분할합니다 3
및 5
그래서 set
때문에 올바르게 구문 분석하지 않습니다 $i
구문 분석에 아무것도하지 않습니다. 즉, 반복 할 값이 인라인되지 않은 경우는 IFS
루프 내부에 배치되어야하며 외부 값은 반복 할 변수에 대해 의도 된 구분 기호를 존중해야합니다. 그 경우에는 $tuples
단순히 IFS=
기본값이며 공백으로 분할 되어야합니다 .
을 설정 / 재설정하지 않고 @ eduardo-ivanec이 제공 한 답변에 따라 IFS
간단히 다음과 같이 할 수 있습니다.
for i in "c 3" "e 5"
do
set -- $i
echo $1 and $2
done
출력 :
c and 3
e and 5
연관 배열 (사전 / hashMap이라고도 함) 사용 :
declare -A pairs=(
[c]=3
[e]=5
)
for key in "${!pairs[@]}"; do
value="${pairs[$key]}"
echo "key is $key and value is $value"
done
bash4.0 이상에서 작동합니다.
쌍 대신 트리플이 필요한 경우 더 일반적인 접근 방식을 사용할 수 있습니다.
animals=(dog cat mouse)
declare -A sound=(
[dog]=barks
[cat]=purrs
[mouse]=cheeps
)
declare -A size=(
[dog]=big
[cat]=medium
[mouse]=small
)
for animal in "${animals[@]}"; do
echo "$animal ${sound[$animal]} and it is ${size[$animal]}"
done
GNU bash, version 4.4.23(1)-release-(x86_64-apple-darwin17.5.0)
brew를 통해 설치된 Mac에서 작동하지 않았 으므로 YMMV입니다.
GNU bash, version 4.3.11(1)-release-(x86_64-pc-linux-gnu)
Docker 컨테이너 내에서 Ubuntu 14.04에서 작동했습니다 .
-A
우리가 -a
.
declare -a indices=(1 2 3); declare -a sound=(barks purrs cheeps); declare -a size=(big medium small)
등의 유무는 아직 터미널에서 그것을 시도하지,하지만 난 생각이 작동합니다.
c=('a' 'c')
n=(3 4 )
for i in $(seq 0 $((${#c[*]}-1)))
do
echo ${c[i]} ${n[i]}
done
때때로 더 편리 할 수 있습니다.
ugly
주석에 언급 된대로 부품 을 설명하려면 :
seq 0 2 는 숫자 0 1 2의 시퀀스를 생성합니다. $ (cmd)는 명령 대체이므로이 예 seq 0 2
에서는 숫자 시퀀스 인을 출력 합니다. 그러나 상한선은 무엇 $((${#c[*]}-1))
입니까?
$ ((something))은 산술 확장이므로 $ ((3 + 4))는 7 등입니다. 우리의 표현은 ${#c[*]}-1
, 그래서 뭔가-1. 우리가 무엇을 안다면 아주 간단 ${#c[*]}
합니다.
c는 배열이고, c [*]는 전체 배열이고, $ {# c [*]}는 배열의 크기이며이 경우에는 2입니다. 이제 모든 것을 롤백합니다. for i in $(seq 0 $((${#c[*]}-1)))
is for i in $(seq 0 $((2-1)))
is for i in $(seq 0 1)
입니다 for i in 0 1
. 배열의 마지막 요소에는 Array-1의 길이 인 인덱스가 있기 때문입니다.
for i in $(seq 0 $(($#c[*]}-1))); do [...]
GNU 병렬 사용 :
parallel echo {1} and {2} ::: c e :::+ 3 5
또는:
parallel -N2 echo {1} and {2} ::: c 3 e 5
또는:
parallel --colsep , echo {1} and {2} ::: c,3 e,5
gnu parallel
brew install parallel
printf
프로세스 대체에서 사용 :
while read -r k v; do
echo "Key $k has value: $v"
done < <(printf '%s\n' 'key1 val1' 'key2 val2' 'key3 val3')
Key key1 has value: val1
Key key2 has value: val2
Key key3 has value: val3
위의 bash
. bash
사용하지 않는 경우 간단한 파이프 라인을 사용하십시오.
printf '%s\n' 'key1 val1' 'key2 val2' 'key3 val3' |
while read -r k v; do echo "Key $k has value: $v"; done
do echo $key $value
done < file_discriptor
예를 들면 :
$ while read key value; do echo $key $value ;done <<EOF
> c 3
> e 5
> EOF
c 3
e 5
$ echo -e 'c 3\ne 5' > file
$ while read key value; do echo $key $value ;done <file
c 3
e 5
$ echo -e 'c,3\ne,5' > file
$ while IFS=, read key value; do echo $key $value ;done <file
c 3
e 5
조금 더 복잡하지만 유용 할 수 있습니다.
a='((c,3), (e,5))'
IFS='()'; for t in $a; do [ -n "$t" ] && { IFS=','; set -- $t; [ -n "$1" ] && echo i=$1 j=$2; }; done
그러나 튜플이 연관 배열이 보유 할 수있는 k / v보다 크면 어떻게 될까요? 3 개 또는 4 개 요소이면 어떨까요? 이 개념을 확장 할 수 있습니다.
###---------------------------------------------------
### VARIABLES
###---------------------------------------------------
myVars=(
'ya1,ya2,ya3,ya4'
'ye1,ye2,ye3,ye4'
'yo1,yo2,yo3,yo4'
)
###---------------------------------------------------
### MAIN PROGRAM
###---------------------------------------------------
### Echo all elements in the array
###---
printf '\n\n%s\n' "Print all elements in the array..."
for dataRow in "${myVars[@]}"; do
while IFS=',' read -r var1 var2 var3 var4; do
printf '%s\n' "$var1 - $var2 - $var3 - $var4"
done <<< "$dataRow"
done
그러면 출력은 다음과 같습니다.
$ ./assoc-array-tinkering.sh
Print all elements in the array...
ya1 - ya2 - ya3 - ya4
ye1 - ye2 - ye3 - ye4
yo1 - yo2 - yo3 - yo4
그리고 요소의 수는 이제 제한이 없습니다. 투표를 찾지 않습니다. 큰 소리로 생각하는 것뿐입니다. REF1 , REF2
내 튜플 정의가 더 복잡한 경우 heredoc에 포함하는 것이 좋습니다.
while IFS=", " read -ra arr; do
echo "${arr[0]} and ${arr[1]}"
done <<EOM
c, 3
e, 5
EOM
이것은 heredoc의 행을 반복하는 것과 원하는 분리 문자에서 행을 분할하는 것을 결합 합니다 .