
Bourne Shell( )에서 배열을 사용하려고 합니다 /bin/sh
. 배열 요소를 초기화하는 방법은 다음과 같습니다.
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
70년대 초 톰슨 쉘이었죠. Bourne 쉘은 1979년 Unix V7에서 이를 대체했습니다.
/bin/sh
그 이후로 수년 동안 Bourne 쉘(또는 BSD에서 무료로 재구현된 Almquist 쉘)이었습니다.
요즘에는 ksh88 언어의 하위 집합(그리고 일부 비호환성이 있는 Bourne 쉘 언어의 상위 집합)을 기반으로 하는 /bin/sh
POSIX 언어에 대한 인터프리터 또는 다른 인터프리터가 더 일반적입니다 .sh
Bourne 쉘 또는 POSIX sh 언어 사양은 배열을 지원하지 않습니다. 또는 위치 매개변수( $1
, $2
, $@
함수당 하나의 배열)라는 하나의 배열만 갖습니다.
ksh88에는 으로 설정한 배열이 있었지만 set -A
구문이 어색하고 유용하지 않기 때문에 POSIX sh에 지정되지 않았습니다.
배열/목록 변수가 있는 다른 셸에는 다음이 포함됩니다. csh
/ tcsh
, rc
, es
, bash
(대부분 ksh 구문을 ksh93 방식으로 복사함), 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
대시로 배열을 시뮬레이션하는 방법(배열의 임의 개수에 맞게 조정 가능): (명령을 사용하려면 ' '(SPACE = 기본값)로 설정되어야 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 ###
################