Bash에서 명령줄 인수의 다음 인수에 액세스하는 방법은 무엇입니까?

Bash에서 명령줄 인수의 다음 인수에 액세스하는 방법은 무엇입니까?

다음이 있다고 가정해 보겠습니다.

for i in $@; do
    echo ${i+1}
done

쉘에서 실행 하면 Why ${i+1} does not work? $ test.sh 3 5 8 4가 출력됩니다 . 1 1 1 1명령줄 인수 목록에서 다음 인수에 액세스하려고 합니다.

답변1

쉘의 각 문자는 특별한 의미를 가질 수 있습니다.

이 코드는 ${i+1}"i + 1"을 의미하지 않습니다.
이것이 무엇을 의미하는지 이해하려면 다음 명령을 실행하십시오.

LESS=+/'\{parameter\:\+word\}' man bash

그리고 읽어보세요:

${parameter:+word}
대체 값을 사용하십시오. 인수가 비어 있거나 설정되지 않은 경우 아무것도 대체되지 않으며, 그렇지 않으면 단어의 확장이 대체됩니다.

조금 위 :

콜론을 생략하면 설정되지 않은 매개변수만 테스트됩니다.

$i루프가 값을 설정 하므로 for i in $@;"대체 값"이 교체되어 1인쇄됩니다.

매개변수 값을 1씩 늘리려면 다음을 수행하십시오.

for    i
do     echo "$((i+1))"
done

필요하지 않습니다 in "$@"(그리고 모든 확장명을 인용하는 데 익숙해집니다).

$ ./test.sh 3 5 8 4
4
6
9
5

이어지는 주장.

그러나 이것은 "다음 주장"도 아닙니다. 핵심 문제는 매개변수의 인덱스가 아닌 매개변수의 값을 사용하는 루프에 있습니다. i각 매개변수의 값 이 아닌 매개변수의 인덱스를 반복해야 합니다 . i그것은 다음과 같습니다:

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

그러면 다음과 같은 색인이 인쇄됩니다.

$ ./test.sh 3 5 8 4
1
2
3
4

간접적인

$iposition의 매개변수에 어떻게 접근하나요 ? : 간접 사용:

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

간단한 !추가가 보이나요?

이제 다음과 같이 실행됩니다.

$  ./test.sh  3 5 8 4
3
5
8
4

마지막 해결책.

현재 매개변수와 다음 매개변수를 인쇄하려면 다음 명령을 사용하십시오.

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

아니요, 변수의 값을 계산하는 것보다 더 쉬운 방법은 없습니다 $j.


$ ./test.sh 3 5 8 4
3 5
5 8
8 4
4 

이는 텍스트에도 적용됩니다.

$ ./test.sh sa jwe yqs ldfgt
sa jwe
jwe yqs
yqs ldfgt
ldfgt 

답변2

귀하의 예제 코드에서 i는 인덱스가 아닌 값입니다.
변수 값을 변수로 사용하려면 느낌표를 사용해야 합니다.
다른 변수를 정의하지 않고는 (i+1)을 작동시킬 수 없습니다. 어쩌면 누군가가 최적화 팁을 줄 수도 있습니다.

check () {
  for i in $(seq $#); do
    let j=i+1
    echo "$i: i=${!i} i+1=${!j}"
  done
}

check a b c

1: i=a i+1=b
2: i=b i+1=c
3: i=c i+1=

답변3

우선 ${i+1}은 매개변수 확장 모드입니다. 즉, 매개변수가 i설정되지 않았거나 null인 경우 의 확장으로 대체되며 1결과는 입니다 1. 따라서 출력에는 모두 1이 표시됩니다.

매개변수 확장이 아닌 산술 연산자를 사용해야 합니다.

예를 들어:

% check () { for i in "$@"; do echo $((i+1)); done ;} 

% check 2 4 5 6
3
5
6
7

답변4

확장됨user79743의위에서 답변했습니다.

--mode delete또는 같은 값을 취하는 매개변수를 원한다고 가정해 보겠습니다 --mode list.

${!i} == "--mode", 우리가 읽고 싶은 값다음과 같은색인( j또는 i+1)을 지정하고 나중에 사용할 수 있도록 보관합니다. 다음 루프 반복에서는 i+1두 번째 검사( j이전 루프, i현재 루프) 를 수행하게 된다는 점을 고려하세요 .

나는 그것이 가변적이라는 것을 알았고 , 그래서 우리는 그것을 1씩 증가시킬 수 있으며, 이는 말하자면 i다음 루프 반복이 될 것임을 의미합니다 .i+2

일반적으로 반복하는 동안 값을 변경하는 것은 현명하지 않다고 말하고 싶습니다. 이 방법은 나에게 정말 효과적이다. 나는 이를 수행하는 여러 가지 (더 나은) 방법이 있을 것이라고 확신합니다.

증가하지 않습니다 i. 일부 인덱스는 여러 번 확인됩니다.

# $ ./test.sh --mode delete 3 5 8 4
# [1]: --mode [2]: delete
# [2]: delete # <-- index [2] is inspected twice
# [3]: 3
# [4]: 5
# [5]: 8
# [6]: 4
for (( i=1; i<=$#; i++)); do
  if [[ ${!i} == "--mode" ]]; then
    j=$((i+1))
    MODE=${!j} # retain for later
    echo "[$i]: ${!i} [$j]: ${!j}"
  else
    echo "[$i]: ${!i}"
  fi
done

증가함에 따라 i각 인덱스는 한 번만 확인됩니다.

# $ ./test.sh --mode delete 3 5 8 4
# [1]: --mode [2]: delete
# [3]: 3
# [4]: 5
# [5]: 8
# [6]: 4
for (( i=1; i<=$#; i++)); do
  if [[ ${!i} == "--mode" ]]; then
    j=$((i+1))
    MODE=${!j} # retain for later
    echo "[$i]: ${!i} [$j]: ${!j}"
    i=$i+1 # <-- incrementing the index
  else
    echo "[$i]: ${!i}"
  fi
done

관련 정보