Jak usunąć nową linię dodaną przez tablicę odczytu podczas używania separatora?

10
VAR=a,b,c,d
# VAR=$(echo $VAR|tr -d '\n')
echo "[$VAR]"
readarray -td, ARR<<< "$VAR"
declare -p ARR

Wynik:

[a,b,c,d]
declare -a ARR=([0]="a" [1]="b" [2]="c" [3]=$'d\n')

Jak mogę powiedzieć, żeby readarraynie dodawać ostatniej linii \n? Jakie jest znaczenie najnowszego $symbolu?

użytkownik1156544
źródło

Odpowiedzi:

13

Niejawny końcowy znak nowej linii nie jest dodawany przez readarraywbudowane, ale przez here-string ( <<<) z bash, zobacz Dlaczego bash tutaj-ciąg dodaje znak końca nowego wiersza? . Możesz się tego pozbyć, drukując ciąg bez użycia nowej linii printfi czytając go za pomocą techniki zastępowania procesów< <()

readarray -td, ARR < <(printf '%s' "$VAR")
declare -p ARR

właściwie by teraz generował

declare -a ARR=([0]="a" [1]="b" [2]="c" [3]="d")
Inian
źródło
3
Łał! Nigdy bym tego nie znalazł. Dzięki
1156544
4

Możesz użyć split + glob (co dzieje się, gdy nie pozostawiasz cudzysłowu w kontekście listy). Przeszkadza nam to przez większość czasu, szkoda byłoby nie korzystać z niego, gdy go potrzebujemy:

IFS=,
set -o noglob

ARR=($VAR) # split+glob with glob disabled, and split using , as delimiter

Jest to nieco mniej skomplikowane niż pisanie pliku tymczasowego, a następnie wywoływanie readarraygo jak w readarray <<< "$string"podejściu (pamiętaj też, że readarray -dpotrzebuje najnowszej wersji bash).

Należy zauważyć, że pomimo Sw IFS(co oznacza separatora ), który działa w ten sam sposób jak readarrayw który a,,b,jest podzielony na "a", ""i "b"tylko.

Dla prawdziwego operatora podziału możesz użyć zshzamiast tego:

ARR=("${(@s:,:)VAR}")

( @i podwójne cudzysłowy, aby zachować puste elementy).

Stéphane Chazelas
źródło
readarray <<< "$string"Zapisuje do pliku tempp a następnie usuwa je zamiast korzystania z pamięci?
user1156544
@ user1156544 Tak.
mosvy
Jak mogę zrobić coś podobnego do twojego ostatniego polecenia w bash? Używam bash 3.3 i próbuję zrekompensować brakreadarray -d
user1156544
3

Puszkowana wersja odpowiedzi @ StéphaneChazelas:

# usage: setarray varname sep string
setarray(){ declare -n a=$1; local IFS=$2 -; set -f; a=($3); }

$ setarray arr , 1,2,3,
$ declare -p arr
declare -a arr=([0]="1" [1]="2" [2]="3")

$ setarray path : "$PATH"
$ setarray ld_preload ': ' "$LD_PRELOAD" # its elements can be separated by either ':' or spaces
...

local -Uczyni opcje takie jak set -f( noglob) lokalne do funkcji, tak jak zmienne.

declare -n a=$1Stworzy lokalną zmienną ajako alias do zmiennej globalnej o nazwie $1(pierwszy argument funkcji).

mosvy
źródło