한 변수의 특정 행을 다른 변수에 할당

한 변수의 특정 행을 다른 변수에 할당

한 변수에서 다른 변수로 특정 행을 전송하고 싶습니다. 나는 이것을 시도했지만 작동하지 않습니다.

c="1.apple
2.banna
3.peach"

read "Please choose fruit [1-3]:" t

a=$c | awk "NR==$t"
echo "You choose: $a"

내 실수는 무엇입니까?

답변1

사용이 문자열은 리디렉션됩니다.<<<~와 함께명령 대체$()그리고 잊지 마세요변수 주위에 큰따옴표 추가:

a=$(awk "NR==$t" <<< "$c")

답변2

첫 번째:

read "Please choose fruit [1-3]:" t

...작동하지 않습니다. shellbuildin에 프롬프트 문자열을 제공하려는 것처럼 보이지만 read옵션 read이 제공되지 않는 한 첫 번째 인수를 변수 이름으로 해석하여 stdin에서 읽은 줄의 값을 할당합니다.

read -p "Please choose fruit [1-3]:" t

...은 많은 쉘에서 지원되는 옵션이며 원하는 작업에 더 가깝습니다.

즉, 이전에 값을 분할하는 방법을 식별하지 않은 한 단일 구분 할당에 여러 값을 쌓아서는 안 됩니다. 이 작업을 수행할 때:

var=' some list of things '

쉘은 결국 이를 다음과 같이 구문 분석합니다.

\0 some list of things \0

...단일 값에 단일 이름을 할당합니다. 많은 쉘은 명명된 배열과 같은 고급 형태의 분리를 제공하지만 모든 POSIX 쉘은 $@함수 컨텍스트별로 쉽게 정의할 수 있는 최소한 하나의 배열, 즉 쉘 배열을 제공합니다. 명명된 배열을 제공하는 다양한 구현은 종종 $@명명된 배열에 대한 셸 배열 동작을 모방하기도 합니다.

따라서 다음과 같이 이러한 모든 개별 값을 단일 문자열에 할당하는 대신:

set apple banana peach

다음과 같이 각 개별 값을 숫자로 개별적으로 처리하여 효과를 확인할 수 있습니다.

printf %s\\n "$1"

...인쇄:

apple

참고 - 9보다 큰 값을 사용하려면 참조를 중괄호로 묶는 것이 좋습니다."${10}"

다음과 같이 고유 문자열 수를 확인할 수 있습니다 "$#".

printf %d\\n "$#"

...인쇄...

3

별도의 문자열 목록에서 이러한 많은 문제를 해결할 수 있습니다. 예를 들면 다음과 같습니다.

printf %s\\n "$@"

...인쇄:

apple
banana
peach

...또는 단일 연결 문자열로 사용됩니다. 예를 들면 다음과 같습니다.

printf %s\\n "$*"

...여기서 개별 배열 값 문자열은 쉘 변수에 포함된 첫 번째 문자에 연결됩니다 $IFS. 따라서 배열의 각 문자열에 기본값이 있으면 $IFS그 사이에 단일 문자열을 사용하여 다음 문자열에 연결됩니다. 예를 들어 위 명령은 다음을 인쇄합니다.<space><tab><newline><space>

apple banana peach

...하지만 그렇게 한다면:

IFS='fruit sucks'; printf %s\\n "$*"

...다음과 같이 인쇄됩니다.

applefbananafpeach

명명된 배열 확장을 구현하는 대부분의 셸은 유사한 구문을 사용하지만 배열 주소를 지정하는 다양한 방법은 이름과 연결되어야 합니다. 배열 할당은 일반적으로 다음과 같습니다.

array=( apple banana peach )

...또는...

array[0]=apple array[1]=banana array[2]=peach

"$1"명명된 배열은 일반적으로 "$#", , 와 "$@"비교 하여 작동 하며 이전에 언급한 과 사이 의 관계가 계속 적용됩니다."$*""${array[1]}""${#array[@]}""${array[@]}""${array[*]}""$*""$IFS""${array[*]}"

가치관을 올바르게 정의하면 문제를 처리하기가 더 쉬워집니다.

set apple banana peach; n=0
{   for a do printf "$((n+=1)).:\t%s\n" "$a"; done
    printf "Please choose fruit [1-$#]: "; read t
} <>/dev/tty >&0 &&
[ "0$((!${#t}))" -lt "0${t##*[!0-9]*}" ] &&
eval 'printf "You choose: %s\n" "${'"$t"}\"

일부는 위의 사용을 비웃을 수 있지만 eval여기서 사용하는 것은 많은 사람들이 원하는 것보다 안전하지 않습니다."${array[$t]}" (이름이 지정된 배열을 사용하여 이를 수행하는 한 가지 방법은 다음과 같습니다.)왜냐하면 처음에 문자열로 구문 분석한 후 "${array[$t]}"두 번째로 평가된다는 의미이기 때문입니다. $t최소한 1과 숫자만 포함되어 있고 0보다 큰지 확인하기 위해 위에서 했던 것처럼 테스트할 필요가 없습니다.(또는 가장 작은 명명된 배열 인덱스의 쉘 구현은 무엇입니까)어느 상황이든 예상치 못한 결과가 발생할 수 있습니다.

관련 정보