![Bash에서 명령줄 인수의 다음 인수에 액세스하는 방법은 무엇입니까?](https://linux55.com/image/83249/Bash%EC%97%90%EC%84%9C%20%EB%AA%85%EB%A0%B9%EC%A4%84%20%EC%9D%B8%EC%88%98%EC%9D%98%20%EB%8B%A4%EC%9D%8C%20%EC%9D%B8%EC%88%98%EC%97%90%20%EC%95%A1%EC%84%B8%EC%8A%A4%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%80%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
다음이 있다고 가정해 보겠습니다.
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
간접적인
$i
position의 매개변수에 어떻게 접근하나요 ? : 간접 사용:
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