Pomyślnie wykonałem funkcję join, która łączy tablicę z łańcuchem za pomocą ogranicznika:
function join() # Usage: string=$(join "delimeter" "${array[@]}" )
{
local array=( "${@:2}" )
OLD_IFS="$IFS"
IFS="$1"
local string="${array[*]}"
IFS="$OLD_IFS"
echo "$string"
}
Próbowałem również stworzyć funkcję split, która powinna działać odwrotnie:
function split() # Usage: array=( $(split "delimeter" "$string") )
{
OLD_IFS="$IFS"
IFS="$1"
local array=( $2 )
IFS="$OLD_IFS"
echo "${array[@]}"
}
Ale kiedy używam polecenia split, a wynik zawiera spacje, nie będzie działać zgodnie z oczekiwaniami. Przykład:
array=( "foo" "bar" "baz" "foo bar" )
string=$(join "|" "${array[@]}")
echo $string
array=( $(split "|" "$string") )
for i in ${array[@]}
do
echo $i
done
Ostatni element „foo bar” również został podzielony. Myślę, że rozwiązaniem jest to, że musisz zrobić array=( "$(split '|' "$string")" )
, ale prawdopodobnie nie wiem, jak zagnieździć cudzysłowy.
2 odpowiedzi
Zauważ, że IFS może być zmienną lokalną w funkcji, więc nie musisz tworzyć kopii zapasowej i przywracać jej wartości:
join () { local IFS="$1"; local s="${@:2}"; printf "%s" "$s"; }
Oto implementacja podziału, która wymaga oceny:
# usage: split varName separator stringToSplit
split () {
local var="$1"
local IFS="$2"
set -- $3
echo "declare -a $var=( $(printf "\"%s\" " "$@") )"
}
Demonstracja
$ a=( foo bar "hello world" baz )
$ s=$(join , "${a[@]}")
$ echo $s
foo,bar,hello world,baz
$ split b , "$s"
declare -a b=( "foo" "bar" "hello world" "baz" )
$ eval $(split b , "$s")
$ for x in "${b[@]}"; do echo "$x"; done
foo
bar
hello world
baz
Problem jest na końcu funkcji split ()
. Serializujesz tablicę z powrotem do ciągu! Jest to więc znowu łańcuch oddzielony spacjami, który nie rozpoznaje, czy spacja była w elementach, czy nie. Wiem więc, że to nie jest zbyt czyste, ale będziesz musiał zwrócić wartość z funkcji split()
za pomocą zmiennej globalnej (pomiń słowo kluczowe local
w przykładzie i uprość wywołanie, a podwójne cudzysłowy w poleceniu for i kilka innych kosmetycznych zmian i działa...:
function split() # Usage: array=( $(split "delimeter" "$string") )
{
OLD_IFS="$IFS"
IFS="$1"
array2=( $2 )
IFS="$OLD_IFS"
}
array=( "foo" "bar" "baz" "foo bar" )
string=$(join "|" "${array[@]}")
echo $string
split "|" "$string"
for i in "${array2[@]}"
do
echo $i
done
Nie wiem, czy istnieje czystszy sposób na uniknięcie zmiennej globalnej, ale wątpię.
Podobne pytania
Nowe pytania
arrays
Tablica to uporządkowana liniowa struktura danych składająca się ze zbioru elementów (wartości, zmiennych lub odniesień), z których każdy jest identyfikowany za pomocą co najmniej jednego indeksu. Pytając o konkretne warianty tablic, użyj zamiast tego powiązanych tagów: [vector], [arraylist], [matrix]. Używając tego znacznika, w pytaniu specyficznym dla języka programowania, oznacz pytanie używanym językiem programowania.