![Unix Bourne Shell의 배열](https://linux55.com/image/38284/Unix%20Bourne%20Shell%EC%9D%98%20%EB%B0%B0%EC%97%B4.png)
/bin/sh
Bourne 쉘( )에서 배열을 사용 하려고 합니다 . 배열 요소를 초기화하는 방법은 다음과 같습니다.
arr=(1 2 3)
하지만 오류가 발생했습니다.
syntax error at line 8: `arr=' unexpected
이제 이 구문에 대해 제가 찾은 게시물에서는 에 대한 것이라고 나와 있지만 bash
Bourne 쉘에 대한 별도의 구문을 찾을 수 없습니다. 구문이 /bin/sh
동일합니까?
답변1
/bin/sh
요즘 시스템에는 Bourne 쉘이 거의 없습니다(Bourne 쉘을 포함하는 마지막 주요 시스템 중 하나인 Solaris도 이제 Solaris 11에서 /bin/sh를 POSIX sh로 전환했습니다). /bin/sh
1970년대 초반 톰슨 포탄입니다. 1979년에는 Bourne 쉘이 Unix V7에서 이를 대체했습니다.
/bin/sh
수년 동안 그것은 Bourne 쉘(또는 BSD에서 무료로 재구현된 Almquist 쉘)이었습니다.
요즘에는 ksh88 언어의 하위 집합(및 Bourne 쉘 언어의 상위 집합이지만 일부 비호환성)을 기반으로 하는 POSIX 언어용 인터프리터 또는 기타 인터프리터가 /bin/sh
더 일반적 입니다.sh
Bourne 쉘 또는 POSIX sh 언어 사양에서는 배열이 지원되지 않습니다. 또는 위치 매개변수( $1
, $2
, $@
, 따라서 각 함수에도 배열이 있음)라는 하나의 배열만 있습니다.
ksh88에는 를 사용하여 설정한 배열이 있지만 set -A
구문이 어색하고 사용하기가 쉽지 않기 때문에 POSIX sh에서는 지정되지 않습니다.
배열/목록 변수가 있는 다른 쉘에는 다음이 포함됩니다: csh
/ tcsh
, rc
, es
, bash
(대부분 ksh93 방식으로 ksh 구문 복사), yash
, zsh
, fish
각각 다른 구문을 사용함( rc
향후 Unix 후속 쉘 fish
및 zsh
가장 일관된 쉘) ...
표준에서 sh
(Bourne 쉘의 최신 버전에서도 작동함):
set '1st element' 2 3 # setting the array
set -- "$@" more # adding elements to the end of the array
shift 2 # removing elements (here 2) from the beginning of the array
printf '<%s>\n' "$@" # passing all the elements of the $@ array
# as arguments to a command
for i do # looping over the elements of the $@ array ($1, $2...)
printf 'Looping over "%s"\n' "$i"
done
printf '%s\n' "$1" # accessing individual element of the array.
# up to the 9th only with the Bourne shell though
# (only the Bourne shell), and note that you need
# the braces (as in "${10}") past the 9th in other
# shells (except zsh, when not in sh emulation and
# most ash-based shells).
printf '%s\n' "$# elements in the array"
printf '%s\n' "$*" # join the elements of the array with the
# first character (byte in some implementations)
# of $IFS (not in the Bourne shell where it's on
# space instead regardless of the value of $IFS)
(Bourne 셸 및 ksh88에서는 이것이 작동하려면 $IFS
공백 문자가 포함되어야 하며 "$@"
(버그) Bourne 셸에서는 위 요소에 액세스할 수 없습니다 $9
( ${10}
작동하지 않지만 여전히 실행하거나 shift 1; echo "$9"
반복할 수 있습니다). ).
답변2
다른 사람들이 말했듯이 Bourne Shell은 그렇지 않습니다.진짜정렬.
그러나 수행해야 하는 작업에 따라 문자열을 구분하는 것만으로도 충분합니다.
sentence="I don't need arrays because I can use delimited strings"
for word in $sentence
do
printf '%s\n' "$word"
done
일반적인 구분 기호(공백, 탭 및 줄 바꿈)가 충분하지 않은 경우 다음을 설정할 수 있습니다.IFS
루프 앞에 원하는 구분 기호.
프로그래밍 방식으로 배열을 작성해야 하는 경우 구분된 문자열을 작성하면 됩니다.
답변3
일반적인 Bourne 쉘에는 배열이 없습니다. 다음을 사용하여 배열을 만들고 반복할 수 있습니다.
#!/bin/sh
# ARRAY.sh: example usage of arrays in Bourne Shell
array_traverse()
{
for i in $(seq 1 $2)
do
current_value=$1$i
echo $(eval echo \$$current_value)
done
return 1
}
ARRAY_1=one
ARRAY_2=two
ARRAY_3=333
array_traverse ARRAY_ 3
배열을 사용하기 위해 어떤 방법을 선택하든 sh
항상 번거롭습니다. 가능하다면 매우 제한된 플랫폼에 제한되어 있거나 무언가를 배우고 싶은 경우가 아니면 Python
다른 언어를 사용하는 것을 고려해 보십시오.Perl
답변4
대시로 배열을 시뮬레이션하는 방법(배열의 임의 크기에 적응할 수 있음): (이 seq
명령을 사용하려면 IFS
" "(공백 = 기본값)로 설정해야 합니다. 이 상황을 피하기 위해 사용하거나 반복 while ... do ...
할 수 있습니다. 코드의 기능을 더 잘 설명하기 위해 범위 내에서 do ... while ...
유지하겠습니다 .)seq
#!/bin/sh
## The following functions implement vectors (arrays) operations in dash:
## Definition of a vector <v>:
## v_0 - variable that stores the number of elements of the vector
## v_1..v_n, where n=v_0 - variables that store the values of the vector elements
VectorAddElementNext () {
# Vector Add Element Next
# Adds the string contained in variable $2 in the next element position (vector length + 1) in vector $1
local elem_value
local vector_length
local elem_name
eval elem_value=\"\$$2\"
eval vector_length=\$$1\_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi
vector_length=$(( vector_length + 1 ))
elem_name=$1_$vector_length
eval $elem_name=\"\$elem_value\"
eval $1_0=$vector_length
}
VectorAddElementDVNext () {
# Vector Add Element Direct Value Next
# Adds the string $2 in the next element position (vector length + 1) in vector $1
local elem_value
local vector_length
local elem_name
eval elem_value="$2"
eval vector_length=\$$1\_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi
vector_length=$(( vector_length + 1 ))
elem_name=$1_$vector_length
eval $elem_name=\"\$elem_value\"
eval $1_0=$vector_length
}
VectorAddElement () {
# Vector Add Element
# Adds the string contained in the variable $3 in the position contained in $2 (variable or direct value) in the vector $1
local elem_value
local elem_position
local vector_length
local elem_name
eval elem_value=\"\$$3\"
elem_position=$(($2))
eval vector_length=\$$1\_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi
if [ $elem_position -ge $vector_length ]; then
vector_length=$elem_position
fi
elem_name=$1_$elem_position
eval $elem_name=\"\$elem_value\"
if [ ! $elem_position -eq 0 ]; then
eval $1_0=$vector_length
fi
}
VectorAddElementDV () {
# Vector Add Element
# Adds the string $3 in the position $2 (variable or direct value) in the vector $1
local elem_value
local elem_position
local vector_length
local elem_name
eval elem_value="$3"
elem_position=$(($2))
eval vector_length=\$$1\_0
if [ -z "$vector_length" ]; then
vector_length=$((0))
fi
if [ $elem_position -ge $vector_length ]; then
vector_length=$elem_position
fi
elem_name=$1_$elem_position
eval $elem_name=\"\$elem_value\"
if [ ! $elem_position -eq 0 ]; then
eval $1_0=$vector_length
fi
}
VectorPrint () {
# Vector Print
# Prints all the elements names and values of the vector $1 on sepparate lines
local vector_length
vector_length=$(($1_0))
if [ "$vector_length" = "0" ]; then
echo "Vector \"$1\" is empty!"
else
echo "Vector \"$1\":"
for i in $(seq 1 $vector_length); do
eval echo \"[$i]: \\\"\$$1\_$i\\\"\"
###OR: eval printf \'\%s\\\n\' \"[\$i]: \\\"\$$1\_$i\\\"\"
done
fi
}
VectorDestroy () {
# Vector Destroy
# Empties all the elements values of the vector $1
local vector_length
vector_length=$(($1_0))
if [ ! "$vector_length" = "0" ]; then
for i in $(seq 1 $vector_length); do
unset $1_$i
done
unset $1_0
fi
}
##################
### MAIN START ###
##################
## Setting vector 'params' with all the parameters received by the script:
for i in $(seq 1 $#); do
eval param="\${$i}"
VectorAddElementNext params param
done
# Printing the vector 'params':
VectorPrint params
read temp
## Setting vector 'params2' with the elements of the vector 'params' in reversed order:
if [ -n "$params_0" ]; then
for i in $(seq 1 $params_0); do
count=$((params_0-i+1))
VectorAddElement params2 count params_$i
done
fi
# Printing the vector 'params2':
VectorPrint params2
read temp
## Getting the values of 'params2'`s elements and printing them:
if [ -n "$params2_0" ]; then
echo "Printing the elements of the vector 'params2':"
for i in $(seq 1 $params2_0); do
eval current_elem_value=\"\$params2\_$i\"
echo "params2_$i=\"$current_elem_value\""
done
else
echo "Vector 'params2' is empty!"
fi
read temp
## Creating a two dimensional array ('a'):
for i in $(seq 1 10); do
VectorAddElement a 0 i
for j in $(seq 1 8); do
value=$(( 8 * ( i - 1 ) + j ))
VectorAddElementDV a_$i $j $value
done
done
## Manually printing the two dimensional array ('a'):
echo "Printing the two-dimensional array 'a':"
if [ -n "$a_0" ]; then
for i in $(seq 1 $a_0); do
eval current_vector_lenght=\$a\_$i\_0
if [ -n "$current_vector_lenght" ]; then
for j in $(seq 1 $current_vector_lenght); do
eval value=\"\$a\_$i\_$j\"
printf "$value "
done
fi
printf "\n"
done
fi
################
### MAIN END ###
################