[bash] Bash의 변수로 정의 된 범위의 숫자를 어떻게 반복합니까?

변수에 범위가 주어지면 Bash에서 숫자 범위를 어떻게 반복합니까?

이 작업을 수행 할 수 있음을 알고 있습니다 (Bash 설명서 에서 “시퀀스 표현”이라고 함 ).

 for i in {1..5}; do echo $i; done

다음을 제공합니다.

1
2
3
4
5

그러나 범위 끝점 중 하나를 변수로 바꾸려면 어떻게해야합니까? 작동하지 않습니다.

END=5
for i in {1..$END}; do echo $i; done

어떤 지문 :

{1..5}



답변

for i in $(seq 1 $END); do echo $i; done

편집 : seq실제로 기억할 수 있기 때문에 다른 방법을 선호 합니다.)


답변

seq방법이 가장 간단하지만 Bash에는 내장 된 산술 평가 기능이 있습니다.

END=5
for ((i=1;i<=END;i++)); do
    echo $i
done
# ==> outputs 1 2 3 4 5 on separate lines

for ((expr1;expr2;expr3));구문은 for (expr1;expr2;expr3)C 및 유사한 언어에서와 마찬가지로 작동하며 다른 ((expr))경우 와 마찬가지로 Bash는이를 산술로 처리합니다.


답변

토론

seqJiaaro가 제안한대로 사용하는 것이 좋습니다. Pax Diablo는 하위 프로세스 호출을 피하기 위해 Bash 루프를 제안했으며 $ END가 너무 큰 경우 메모리 친화적 인 이점이 있습니다. Zathrus는 루프 구현에서 일반적인 버그를 발견했으며 i텍스트 변수 이기 때문에 연관된 숫자로 연속 변환을 수행 한다는 것을 암시했습니다 .

정수 산술

이것은 Bash 루프의 개선 된 버전입니다.

typeset -i i END
let END=5 i=1
while ((i<=END)); do
    echo $i
    
    let i++
done

우리가 원하는 유일한 것이 있다면, echo우리는 쓸 수 echo $((i++))있습니다.

대변인 은 나에게 무언가를 가르쳤다 : 배쉬는 for ((expr;expr;expr))구조물을 허용한다 . Bash에 대한 전체 매뉴얼 페이지를 읽지 못했기 때문에 (Korn shell ( ksh) 매뉴얼 페이지를 사용하여 오래 전에했듯이) 그리워했습니다.

그래서,

typeset -i i END # Let's be explicit
for ((i=1;i<=END;++i)); do echo $i; done

seq아마도 가장 빠르지는 않지만 메모리를 효율적으로 사용하는 방법으로 보입니다 ( 출력 을 소비하기 위해 메모리를 할당 할 필요는 없습니다 .

초기 질문

eschercycle은 { a .. b } Bash 표기법은 리터럴에서만 작동합니다. Bash 매뉴얼에 따라 true입니다. 하나 하나의 (내부)이 장애물을 극복 할 수 fork()없이를 exec()(호출의 경우와 같이 seq다른 화상 되 포크 + 간부를 요구하는가) :

for i in $(eval echo "{1..$END}"); do

모두 evalecho배시 내장 매크로는하지만,이 fork()명령 교체합니다 (필요 $(…)구조체).


답변

원래 표현이 효과가없는 이유는 다음과 같습니다.

에서 남자 bash는 :

중괄호 확장은 다른 확장보다 먼저 수행되며 다른 확장에 특수한 문자는 결과에 유지됩니다. 엄격하게 텍스트입니다. Bash는 확장 컨텍스트 또는 중괄호 사이의 텍스트에 구문 적 해석을 적용하지 않습니다.

따라서 중괄호 확장매개 변수 확장 전에 순수 텍스트 매크로 작업으로 초기에 수행되는 작업 입니다.

쉘은 매크로 프로세서와보다 공식적인 프로그래밍 언어 사이에서 고도로 최적화 된 하이브리드입니다. 일반적인 사용 사례를 최적화하기 위해 언어가 다소 복잡해지고 일부 제한이 허용됩니다.

추천

Posix 1 기능을 고수하는 것이 좋습니다 . 이는 for i in <list>; do목록이 이미 알려진 경우을 사용하는 것을 의미합니다 . 그렇지 않으면 다음 과 같이 while또는을 사용하십시오 seq.

#!/bin/sh

limit=4

i=1; while [ $i -le $limit ]; do
  echo $i
  i=$(($i + 1))
done
# Or -----------------------
for i in $(seq 1 $limit); do
  echo $i
done


1. Bash는 훌륭한 쉘이며 대화식으로 사용하지만 스크립트에 bash-ism을 넣지 않습니다. 스크립트는 더 빠른 쉘,보다 안전한 쉘, 임베디드 스타일의 스크립트가 필요할 수 있습니다. / bin / sh로 설치된 모든 항목에서 실행해야 할 수 있으며 일반적인 프로 표준 인수가 모두 있습니다. 쉘 쇼크 ( 일명 bashdoor)를 기억 하십니까?


답변

POSIX 방식

이식성에 관심이 있다면 POSIX 표준예제를 사용하십시오 .

i=2
end=5
while [ $i -le $end ]; do
    echo $i
    i=$(($i+1))
done

산출:

2
3
4
5

POSIX 가 아닌 것 :


답변

간접적 인 또 다른 계층 :

for i in $(eval echo {1..$END}); do
    


답변

당신이 사용할 수있는

for i in $(seq $END); do echo $i; done