Bash 괄호 확장에서 변수를 사용할 수 있습니까?


10

아래는 내가 달성하려는 것에 대한 일종의 의사 코드입니다.

#!/bin/bash

# I already have the variable below figured out (positive integer):
numlines=$([returns number of lines containing specific characters in a file])

# This is basically what I want to do with it:
for i in {1..$numlines}; do
    # the part below is already figured out as well:        
    do some other stuff
done

`{1..n} '시퀀스에 실제 숫자를 삽입하여 명령 행에서 제대로 실행할 수 있습니다. 여기에 변수를 포함시킬 수 있는지 여부와 변수 수행 방법을 알아야합니다.

  • 나는 export그것을 시도 했다
  • 변수 자체를 시퀀스 안에 중괄호로 묶어 보았습니다. {1..${numlines}}
  • 나는 그것이 확장되기를 바라고 큰 따옴표로 묶어 보았습니다. {1.."$numlines"}
  • 나는 탈출을 시도했다 $:{1..\$numlines}

set -[something]이 변수를 확장하려면 명령 을 사용해야 합니까? 나는 심지어 eval... all을 사용하는 몇 가지 형태를 사용해 보았습니다 .

내가 놓친 것이 단순하거나 모호한 것이 있는지 또는 더 이상 시간을 낭비하기 전에 이것이 가능한지 알아야합니다.

필요에 따라 작동하도록 실제로 해킹하는 방법을 함께 던질 수는 있지만 가능한 한 피하고 가능한 한 올바른 방법을 배우고 싶습니다.


답변:


11

불행하게도 변수 확장은 중괄호 확장 후에 발생하므로 해당 확장 (AFAIK)에서 변수를 사용할 수있는 방법이 없습니다.

다행히도 동일한 작업을 수행하는 도구가 있습니다.

for i in $(seq 1 $numlines); do
    # stuff
done

seqGNU coreutils에서 온 것입니다. POSIX에서 어떻게하는지 모릅니다.


1
(플러스 1). seqGNU 시스템에 유용하며, 올바르게 기억한다면 최신 OSX입니다. 다른 BSD 시스템에서는 대신 jot 를 사용할 수 있습니다 .
John1024

seq완벽하게 작동합니다. 신속한 답변 감사합니다.
rubynorails

이것은 내 질문의 일부는 아니지만이를 역순으로 수행하는 구문은 무엇 {16..1}입니까? $(seq $numlines 1)작동하지 않았다. 나는 항상 할 수 있다고 생각 man seq하지만, 누군가가 그들의 머리 꼭대기를 알고 있는지 궁금합니다.
rubynorails

1
이 링크 에서 반대로하는 방법을 알아 냈습니다. –for i in $(seq $numlines -1 1)
rubynorails

seq ${numlines} -1 0
DopeGhoti

10

확실한. 정수 변수를 증가시키는 for 루프가 필요한 경우 정수 변수 를 증가시키는 for루프 형식을 사용하십시오 (또는 일반적으로 루프 변수에서 산술을 수행함).

for ((i=1; i<=numlines; i++)); do  done

이 구문은 bash (및 ksh93 및 zsh)에서 작동하지만 일반 sh에서는 작동하지 않습니다. 일반 sh에서는 while 루프와 테스트 ( [ … ]) 구문을 사용하십시오.

i=1
while [ "$i" -le "$numlines" ]; do
  
  i=$((i+1))
done

8

당신이하지 않도록해야합니다 seq톰 헌트가 지적 하듯이에 대한 일반적인 솔루션을 것으로 보인다, 다음 eval확실히 할 수 그것을 (하지만, 나는 그것을 권장하지 것이다) 수행

eval 'for i in {1..'$numlines'}; do echo $i; done'

{} 확장을 피함으로써 POSIX를 유지할 수 있으며 간단히 수학과 정수를 비교할 수 있습니다 $numlines.

while [ ! "$numlines" -eq 0 ]; do
     echo "$numlines"
     : $((numlines-=1))
done

POSIX의 외부, bash그리고 ksh하고 zsh또한 C-스타일이 for루프 :

for((i=0; i<numlines; i++)); do echo $i; done

1
이 답변도 정말 감사합니다. 하지만 seq내 시나리오에 대한 벌금을 근무하고 간단한 해결책이 될 듯, 그것은 (심지어 POSIX) 다른 대안이 있다는 것을 알 수있는 좋은입니다. 고마워
rubynorails

2
사용할 이유가 없습니다 eval. 중괄호 확장이 있으면 C 스타일 루프가 있습니다.
chepner

@PSkocik-2 개의 답변을 선택할 수 있다면이 답변도 선택합니다. 이 작업을 반대로 수행해야한다는 사실을 알게되었을 때 귀하의 eval예는 가장 단순했으며를 사용하여 대체 방법을 검색하지 않아도됩니다 seq. while루프는 나에게 약간의 부피이다. 나는 일을 짧고 달콤하게 유지하고 싶고 0 또는 1의 값을 for주어 C 스타일 루프를 작동 시킬 수 i없었습니다. 올바르게 반환되지 않았으며 항상 조금 벗어났습니다. 제대로 작동하도록 조정할 수는 있지만 확실하게 유용한 솔루션입니다.
rubynorails

eval루프 몸체 내부에 사소한 것이 있으면 이 방법이 문제가됩니다. 그런 두 개의 루프를 중첩 해야하는 경우 읽기가 쉽지 않을 것이라고 생각합니다.
kasperd
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.