변수에 범위가 주어지면 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는이를 산술로 처리합니다.
답변
토론
seq
Jiaaro가 제안한대로 사용하는 것이 좋습니다. 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
모두 eval
와 echo
배시 내장 매크로는하지만,이 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 가 아닌 것 :
(( ))
POSIX 자체에서 언급했듯이 일반적인 확장이지만 달러는 없습니다 .[[
.[
여기에 충분합니다. 참조 : 배쉬에서 단일 및 이중 대괄호 사이의 차이점은 무엇입니까?for ((;;))
seq
(GNU Coreutils){start..end}
Bash 매뉴얼에서 언급 한대로 변수와 함께 사용할 수 없습니다 .let i=i+1
: POSIX 7 2. 쉘 명령 언어 에 단어가 포함되어 있지 않으며 4.3.42에서let
실패합니다.bash --posix
-
의 달러가
i=$i+1
필요할 수도 있지만 확실하지 않습니다. POSIX 7 2.6.4 산술 확장에 따르면 :쉘 변수 x에 선택적으로 선행 더하기 또는 빼기 기호를 포함하여 유효한 정수 상수를 형성하는 값이 포함 된 경우 산술 확장 “$ ((x))”및 “$ (($ x))”는 동일한 값을 반환합니다. 값.
그러나 문자 그대로 읽는 것은 변수가 아니기
$((x+1))
때문에 확장 한다는 것을 의미하지는x+1
않습니다.
답변
간접적 인 또 다른 계층 :
for i in $(eval echo {1..$END}); do
∶
답변
당신이 사용할 수있는
for i in $(seq $END); do echo $i; done