쉘 스크립트“for”루프 구문


191

나는 일하기 위해 다음을 얻었습니다.

for i in {2..10}
do
    echo "output: $i"
done

이 라인의 무리를 생산 output: 2, output: 3등등.

그러나 다음을 실행하려고합니다.

max=10
for i in {2..$max}
do
    echo "$i"
done

다음을 생성합니다.

output: {2..10}

컴파일러가 $ max를 배열의 다른 끝으로 취급해야하며 문자열의 일부가 아니라는 것을 어떻게 알 수 있습니까?


2
어떤 시스템과 쉘을 사용하고 있습니까? 어떤 종류의 구피 시스템에 sh 또는 bash가 있지만 coreutil 인 seq는 없습니까?
whatsisname

11
FreeBSD는 그렇지 않습니다.
Nietzche-jou

echo "$i해야 echo "$i"- 그래도 문제가 해결되지 않습니다.
Dave Jarvis

작은 스타일의 니트 : 나는 보통 볼 dothen같은 같은 줄에 키워드 forif각각. 예 :for i in {2..10}; do
유료 괴상한

답변:


234

괄호 확장, {x..y} 는 다른 확장보다 먼저 수행되므로 가변 길이 시퀀스에는이를 사용할 수 없습니다.

대신, 사용자 mob가 언급 한대로이seq 2 $max 방법을 사용하십시오 .

예를 들어 다음과 같습니다.

max=10
for i in `seq 2 $max`
do
    echo "$i"
done

seqfor 루프에서 숫자를 세고 증가시키는 것과 같은 외부 명령을 사용해야 할 이유가 없으므로을 사용하지 않는 것이 좋습니다 seq. 이 명령은 이전 bash와의 호환성을 위해 남겨졌습니다. 내장 명령은 충분히 빠릅니다. for (( EXP1; EXP2; EXP3 )) ...
miller

13
@miller for (( ... ))구문은 POSIX가 아니기 때문에 Alpine Linux와 같은 것에서는 즉시 작동하지 않습니다. seq그렇습니다.
Wernight

@Wernight 알파인 리눅스뿐만 아니라; #!/bin/sh데비안 / 우분투에서 대시입니다.
Franklin Yu

72

의 산술 표현 버전을 사용해보십시오 for:

max=10
for (( i=2; i <= $max; ++i ))
do
    echo "$i"
done

이것은 대부분의 bash 버전에서 사용 가능하며 Bourne 쉘 (sh)과 호환되어야합니다.


1
@Flow : 흠, 방금 #! / bin / sh가있는 몇 가지 시스템 (Linux 및 BSD 기반)에서 시도했지만 정상적으로 작동했습니다. bash와 특히 / bin / sh에서 호출되어 여전히 작동했습니다. 어쩌면 sh의 버전이 중요합니까? 오래된 유닉스에 있습니까?
시스템 일시

8
전용 시스템을 가진 시스템은 거의 없으며 다른 시스템을 sh다른 쉘로 연결합니다. 이상적으로, 이러한 쉘은 호출 sh POSIX 표준에서 이러한 기능을 지원하지만, 기본적으로 통해 추가 기능의 일부를 보자. C 스타일 for-loop는 POSIX 기능이 아니지만 sh실제 쉘에 의해 모드에 있을 수 있습니다 .
chepner

27

루프를 수동으로 단계 :

i = 0
최대 = 10
[$ i -lt $ max] 동안
하다
    에코 "출력 : $ i"
    진정한 $ ((i ++))
끝난

완전히 POSIX 일 필요는없는 경우 산술 for 루프를 사용할 수 있습니다 .

최대 = 10
for ((i = 0; i <max; i ++)); 에코 "출력 : $ i"; 끝난

또는 사용 BSD 시스템에서 jot (1)을 .

i의 경우 $ (jot 0 10); 에코 "출력 : $ i"; 끝난

3
true $(( i++ ))모든 경우에 작동하는 것은 아니므로 대부분의 이식성이 있습니다 true $((i=i+1)).
흐름

세미콜론은 "for ((i = 0; i <max; i ++));"
logan

9

여러 가지 방법이 있습니다.

max=10
for i in `eval "echo {2..$max}"`
do
    echo "$i"
done

7
보안 위험 eval은 설정 한 모든 것을 평가 max하기 때문입니다. 를 고려한 max="2}; echo ha; #"다음 echo ha더 파괴적인 것으로 교체하십시오 .
chepner

6
(S) 그는 최대 10을 설정했습니다. 위험이 없습니다.
콘래드 마이어

9

seq시스템 에서 명령을 사용할 수있는 경우 :

for i in `seq 2 $max`
do
  echo "output: $i"
done

그렇지 않은 경우 가난한 사람을 다음 seq과 함께 사용하십시오 perl.

seq=`perl -e "\$,=' ';print 2..$max"`
for i in $seq
do
  echo "output: $i"
done

그 인용 부호를보십시오.


방금 확인했습니다. 그렇지 않은 것 같습니다.
eykanal

5

이것은 방법입니다 :
Bash :

max=10
for i in $(bash -c "echo {2..${max}}"); do echo $i; done

위의 배쉬 방법에 대한 작동 kshzsh도,시는 bash -c대체됩니다 ksh -c또는 zsh -c각각.

참고 : 및 for i in {2..${max}}; do echo $i; done에서 작동합니다 .zshksh


4

C 프로그래밍처럼 루프를 반복 할 수 있습니다.

#!/bin/bash
for ((i=1; i<=20; i=i+1))
do 
      echo $i
done

2

여기서는 Mac OS X에서 작동했습니다.

BSD 날짜의 예, 날짜를 늘리고 줄이는 방법도 포함됩니다.

for ((i=28; i>=6 ; i--));
do
    dat=`date -v-${i}d -j "+%Y%m%d"` 
    echo $dat
done

2

seq시스템에 명령이 설치되어 있지 않기 때문에 (Mac OS X v10.6.1 (Snow Leopard)) while대신 루프를 사용했습니다.

max=5
i=1

while [ $max -gt $i ]
do
    (stuff)
done

* 어깨를 으 * * 작동하는 것.


2
seq는 비교적 새롭습니다. 몇 달 전에 만 알게되었습니다. 그러나 'for'루프를 사용할 있습니다 !! 'while'의 단점은 루프 내부의 어딘가에서 카운터를 증가 시키거나 아래쪽으로 루프하는 것을 기억해야한다는 것입니다.
시스템 일시

1

이들은 모두 {1..8}POSIX 여야합니다. continue루프에 조건부를 넣으면 중단되지 않습니다 . 정식 방법 :

f=
while [ $((f+=1)) -le 8 ]
do
  echo $f
done

또 다른 방법:

g=
while
  g=${g}1
  [ ${#g} -le 8 ]
do
  echo ${#g}
done

그리고 또 다른:

set --
while
  set $* .
  [ ${#} -le 8 ]
do
  echo ${#}
done

1

사용하다:

max=10
for i in `eval echo {2..$max}`
do
    echo $i
done

변수 대체 후 {}을 재평가하려면 명시적인 'eval'호출이 필요합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.