1에서 N까지 mksh for 루프를 만드는 방법

1에서 N까지 mksh for 루프를 만드는 방법

그래서 나는 이렇게 하려고 노력한다

for x in {1..7000}
do
   echo $x
done

출력은 다음과 같습니다{1..7000}

또한 C 스타일 for 루프가 mksh에서 작동하지 않는다는 것도 배웠습니다.

인터넷 검색을 좀 했지만 대부분 mksh가 아닌 ksh에 대한 정보입니다.

그렇다면 mksh에서 범위를 반복하는 올바른 방법은 무엇입니까?

노트:나는 문자열을 인쇄하는 것보다 반복과 C와 유사한 동작을 생성하는 올바른 방법에 더 관심이 있습니다.

답변1

그럼 먼저, 있는 그대로여기서 간략하게 논의했습니다일반적인 형태...

for arg in {brace..expanded..set}; do ...

...내 생각에는 이것이 쉘 프로그래밍 오류의 대표적인 예입니다. 루프에서 수식 세트를 생성하고 각 결과를 구분된 배열에 저장한 후 다음으로 전달합니다.또 다른 루프배열을 반복할 목록으로 나타냅니다.

일반적으로 대괄호 확장은 프로그래밍 환경에서 특별히 유용하지 않습니다. 왜냐하면 모든 쉘 프로그래밍은 어떤 방식으로든매크로그리고 버팀대 확장이미 매크로임. 버팀대 확장은(나도 생각한다)굉장히 유용하다대화형 셸 기능은 매크로이기 때문에 유용합니다. 그렇지 않으면 낭비가 됩니다.

지원 확장도 이식 가능하지 않습니다.(읽기: POSIX - 휴대용). 내가 아는 한, 일반적으로 현재 버전의 zsh, bash, , 에서는 작동할 수 있지만 yash다른 곳에서는 작동하지 않습니다. 이러한 셸에서도 셸 옵션을 사용하여 비활성화할 수 있으므로 일반적으로 또는 의 출력에서 ​​가용성을 테스트할 수 있지만 ksh93셸 기능의 맥락에서 절대적으로 의존할 수는 없습니다 . 그 사이에 위의 쉘 각각에는 서로 다른 종류의 테스트가 필요하므로 이를 함수에 사용하여 테스트하고 싶다면 대상 쉘의 매뉴얼에서 구체적인 내용을 확인하시기 바랍니다.$-set +o

다른 셸에서는 명령 대체의 출력을 분할하여 거의 동일한 동작을 얻을 수 있습니다. 단, 컬렉션을 생성하려면 외부 실행 파일을 호출해야 한다는 점만 다릅니다 $IFS. 이는 프로그램 seq을 사용할 수 있는 곳에서 쉽게 시연됩니다. 예를 들어…

unset IFS       
### ^ensure $IFS default behavior
for arg in $(seq 7000)
do  printf %d\\n "$arg"
done

...또는...

unset IFS
printf %d\\n $(seq 7000)

...하지만 쓰여진 대로 둘 다 단점 외에는 아무것도 제공하지 않습니다...

seq 7000

그러나 첫 번째 예의 경우 방법은 중괄호 확장 버전과 거의 동일합니다. 두 경우 모두, 일부 다른 함수나 프로세스는 완전한 인수 목록을 생성한 for다음 컨트롤 생성자에 의해 반복됩니다. 그러나 후자의 경우,(이외의 쉘의 ksh93경우파이프 열기/해체도 있으며, 셸 프로세스와 해당 하위 프로세스를 분기 seq하고 마지막으로 $IFS.

$IFS그런데 분할은 사용된 껍질에 따라 매우 다른 속도로 발생합니다. bash예를 들어, 단순 $IFS분할 성능은 종종 형편없지만 dash분할 문자열의 줄 길이에 따라 중괄호 확장을 수행하는 다른 쉘만큼 빠를 수도 있습니다.

그러나 중괄호 확장을 사용하든 분할을 사용하든 관계없이 $IFS최종 결과는 일부 루프를 실행하여 수식 목록을 생성한 다음 다른 루프를 실행하여 해당 목록을 반복하는 것입니다. 대신, 여러분이 할 수 있고 아마도 해야 할 일은 목록을 생성한 수식의 적용에 대해 루프를 실행하고, 사용된 반복자를 가능한 한 빨리 처리하고, 만족스러운 결과를 위해 각 반복을 테스트하는 것입니다. C에서는 이런 일을 할 것입니다 ...

for ( x = 0; x < 10; x++ ){ ...

이는 실제로 에서 수행할 수 있는 작업과 유사 하거나 에서 bc사용할 수 있는 편리한 구문 형식과 매우 유사합니다.ksh93zshbash

for (( x=0; x<10; x++ )); do ...

그러나 이것도 휴대용이 아닙니다.(다시 읽기: POSIX). 대신 다음을 이식 가능하게 수행할 수 있습니다.

iterator=$(( start_value - interval ))
while [ "$(( iterator += interval ))" -le "$end_value" ]; do ...

...또는...

iterator=$(( start_value - interval ))
while [ "$(( ( iterator += interval ) <= end_value ))" -ne 0 ]; do ...

POSIX 지정C 산술 연산(즉, 정수가 포함되는 경우)에 대한 쉘 산술 확장 및 기능 패리티 검사와 유사합니다. 결과적으로 단 한 번의 확장으로 복잡한 수식을 편리하고 이식성 있게 반복할 수 있으며, 여러 변수를 동시에 동시에 반복할 수도 있습니다.

반면에 이러한 구성은 다른 C 언어와 셸 언어의 불평등을 해결하기 어렵게 만들 수 있습니다. 쉘 읽기 및 쓰기는 거의 항상 리터럴 s 및 s(각 시스템 호출 자체)이며 read()쉘 구문에는 이식 가능 및 /또는 아날로그가 write()없습니다 . 따라서 각 반복에서 이러한 작업을 수행하는 루프는(이 작업을 수행하기 위해 내장 함수만 사용하는 경우에도) 성능 저하를 초래할 수 있습니다.fread()fwrite()setbuf()

그러나 때로는 쉘 스크립트에서 전체 컬렉션을 순차적으로 또는 병렬로 빌드하고 실행하는 것 사이에서 절충안을 찾을 수 있습니다.

set 0 1 2 3 4 5 6 7 8 9
for n do printf "$n%d\n" "$@"; done

이 작업은 write()10번 반복하여 10번 수행되며 00 - 99 사이에서 개행으로 구분된 시퀀스를 인쇄합니다. 이것은 매우 작은 예이고 여전히 낭비입니다. 30바이트 write()는 3바이트에 비해 크게 개선된 것이 아니기 때문입니다. write()그러나 이는 여러분이 사용할 수 있는 이러한 유형의 접근 방식을 보여주는 것입니다. 앞서 말했듯이 쉘 프로그래밍 언어는 매우 유용하다.매크로내부에모든 것은 문자열이다. 따라서 대상 세트를 더 작고 관리하기 쉬운 세트로 나눈 다음 루프 컨텍스트에서 반복적으로 호출하여 궁극적으로 대상 세트를 생성할 수 있는 경우 더 성능이 좋은 결과를 얻을 수 있는 경우가 많습니다.

다음은 좀 더 복잡하고 매크로와 유사한 예입니다.

sh -c '
    i=0 _i=-25
    set "$1" "$1" "$1" "$1" "$1"
    for n do eval "
        printf %b%d $@ $@ $@ $@ $@"
done' -- \
    '"\01$((1+(i<(i+=!(_i=(_i+=25)%275)))))" "$i$_i"'

write()각각 평균 ​​약 100바이트에 대해 5번 반복하고 다음을 인쇄합니다.

10      125     150     175     1100    1125    1150    1175    1200    1225    1250
20      225     250     275     2100    2125    2150    2175    2200    2225    2250
30      325     350     375     3100    3125    3150    3175    3200    3225    3250
40      425     450     475     4100    4125    4150    4175    4200    4225    4250
50      525     550     575     5100    5125    5150    5175    5200    5225    5250
60      625     650     675     6100    6125    6150    6175    6200    6225    6250
70      725     750     775     7100    7125    7150    7175    7200    7225    7250
80      825     850     875     8100    8125    8150    8175    8200    8225    8250
90      925     950     975     9100    9125    9150    9175    9200    9225    9250
100     1025    1050    1075    10100   10125   10150   10175   10200   10225   10250
110     1125    1150    1175    11100   11125   11150   11175   11200   11225   11250
120     1225    1250    1275

관련 정보