첫 번째 인수를 제외한 $ @


36

이런 식으로 실행되는 쉘 스크립트를 작성해야합니다.

./myscript arg1 arg2_1 arg2_2 arg2_3 ....... arg2_#

스크립트 안에 for 루프가 있습니다

for i in $@

그러나 내가 아는 것처럼 $ @에는 $ 1에 최대 $ ($ #-1)이 포함됩니다. 그러나 내 프로그램의 경우 $ 1은 $ 2 $ 3 $ 4 등과 분명히 다릅니다. $ 2에서 끝까지 반복하고 싶습니다 ... 어떻게 이것을 달성합니까? 고맙습니다:)

답변:


47

첫째, $@따옴표가 없으면 의미가 없으므로 사용해서는 안됩니다. $@따옴표 ( "$@") 및 목록 컨텍스트 에서만 사용해야 합니다.

for i in "$@" 목록 컨텍스트로 규정되지만 여기에서 위치 매개 변수를 반복하기 위해 표준적이고 가장 이식 가능하며 간단한 형식은 다음과 같습니다.

for i
do something with "$i"
done

이제 두 번째 요소부터 시작하여 요소를 반복하려면 표준적이고 가장 이식 가능한 방법을 사용하십시오 shift.

first_arg=$1
shift # short for shift 1
for i
do something with "$i"
done

shift, 무엇을 사용하는 수 $1목록에서 제거 된 (하지만 우리는 그것을 저장 한 $first_arg) 무엇에로 사용하기 $2에 지금있다 $1. 위치 매개 변수가 한 시프트 1 (좌에 위치 shift 2... (2)에 의해 시프트 참조). 따라서 기본적으로 루프는 두 번째 인수였던 것에서 마지막 것까지 반복됩니다.

bash(과 zsh하고 ksh93있지만,의 IT), 대안은 할 수 있습니다 :

for i in "${@:2}"
do something with "$i"
done

그러나 표준 sh구문이 아니므로로 시작하는 스크립트에서는 사용하지 않아야합니다 #! /bin/sh -.

에서 zsh또는 yash, 당신은 할 수 있습니다 :

for i in "${@[3,-3]}"
do something with "$i"
done

세 번째 인수에서 세 번째 인수로 반복합니다.

에서는 zsh, $@도라고도 $argv어레이. 따라서 배열의 시작 또는 끝에서 요소를 팝하려면 다음을 수행하십시오.

argv[1,3]=() # remove the first 3 elements
argv[-3,-1]=()

( shift도 쓸 수 1=()zsh)

에서 bash, 당신은 단지에 할당 할 수있는 $@을 가진 요소 set, 그래서 결국 오프 3 개 요소를 팝업, 내장이 뭔가를 같이 할 것입니다 :

set -- "${@:1:$#-3}"

그리고 세 번째에서 세 번째로 반복하려면 :

for i in "${@:3:$#-5}"
do something with "$i"
done

POSIXly의 마지막 3 개 요소를 팝하려면 "$@"루프를 사용해야합니다.

n=$(($# - 3))
for arg do
  [ "$n" -gt 0 ] && set -- "$@" "$arg"
  shift
  n=$((n - 1))
done

2
대체 (못생긴) bash는 가능성 : 간접 변수 :for ((i=2; i<=$#; i++)); do something with "${!i}"; done
글렌 잭맨

나는 ++ : C와 더 잘 알고 있기 때문에 나는이 버전에 더 익숙
user40780

10

나는 당신이 shift내장 을 원한다고 생각합니다 . 그것은 이름 변경 $2$1, $3$2, 등

이처럼 :

shift
for i in "$@"; do
    echo $i
done

for 루프에서 어떻게 달성 할 수 있습니까? 고맙습니다.
user40780

1
당신은하지 않습니다-당신은 for루프에 들어가기 전에 그것을 사용하고 , 당신은 단지 $ @를 통해 정상적으로 반복합니다. shift통화 후 $ @는arg2_1 arg2_2 arg2_3...
John

그러나 한 가지 더 질문이 있습니다. $ 1에서 $ ($ #-2)까지 반복하고 싶다고 가정합니다 (예 : arg_2_ #을 제외하고 arg_1 ~ arg_2 _ #-1까지). 어떻게해야합니까?
user40780

2

원시인 접근 방식은 항상 있습니다.

first=1
for i
do
        if [ "$first" ]
        then
                first=
                continue
        fi
        something with "$i"
done

이것은 $@그대로 유지하고 (나중에 사용하려는 경우) 모든 인수를 반복하지만 첫 번째 인수는 처리하지 않습니다.


1

bash에서 명시 적 인덱싱으로 루프를 작성할 수도 있습니다.

for ((i=2; i<=$#; ++i)); do
  process "${!i}"
done

이것은 두 번째 인수에서 마지막 인수까지 모든 인수를 반복합니다. 마지막 인수를 제외하려면 간단히

for ((i=1; i<=$#-1; ++i)); do
  process "${!i}"
done

다른 모든 주장 만 취하고 싶다면 다음과 같이 쓰십시오.

for ((i=1; i<=$#; i+=2)); do
  process "${!i}"
done

이것에 대한 이야기 는 내장 함수산술 버전 과 인수 개수변수 간접 참조 입니다.for$#${…}

멋진 응용 프로그램 중 하나는 이것을 사용하여 주어진 옵션이 옵션을 따르는 인수를 값으로 사용할지 여부를 루프 내에서 결정할 수 있다는 것입니다. 그렇다면 다음 값을 소비하고 반복하는 동안 건너 뛰려면 증가 i(예 : writing : $((++i)))하십시오.

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