Bagaimana cara menghapus baris baru yang ditambahkan oleh readarray saat menggunakan pembatas?

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

Hasil:

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

Bagaimana saya bisa mengatakan readarrayuntuk tidak menambahkan baris terakhir \n? Apa arti dari $simbol terbaru ?

pengguna1156544
sumber

Jawaban:

13

Karakter baris baru trailing implisit tidak ditambahkan oleh readarraybuiltin, tetapi oleh string-sini ( <<<) dari bash, lihat Mengapa bash di sini-string menambahkan char baris baru trailing? . Anda dapat menghilangkannya dengan mencetak string tanpa menggunakan baris baru printfdan membacanya melalui teknik substitusi proses< <()

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

akan menghasilkan dengan benar sekarang

declare -a ARR=([0]="a" [1]="b" [2]="c" [3]="d")
Inian
sumber
3
Wow! Saya tidak akan pernah menemukan ini. Terima kasih
user1156544
4

Anda bisa menggunakan split + glob (apa yang terjadi ketika Anda membiarkan ekspansi tidak dikutip dalam konteks daftar). Itu menghalangi sebagian besar waktu kita, akan memalukan untuk tidak menggunakannya ketika kita benar-benar membutuhkannya:

IFS=,
set -o noglob

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

Itu sedikit kurang berbelit-belit daripada menulis file temp dan kemudian memanggilnya readarrayseperti dalam readarray <<< "$string"pendekatan (juga perhatikan bahwa readarray -dperlu versi yang sangat baru bash).

Perhatikan bahwa meskipun Sdalam IFS(yang merupakan pemisah ), itu bekerja dengan cara yang sama seperti readarraydalam yang a,,b,dibagi menjadi "a", ""dan "b"hanya.

Untuk operator pemisahan nyata, Anda bisa menggunakan zsh:

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

( @Tanda kutip ganda dan untuk melestarikan elemen kosong).

Stéphane Chazelas
sumber
The readarray <<< "$string"menulis ke file tempp dan kemudian menghapus itu bukan menggunakan memori?
user1156544
@ user1156544 Ya.
Mosvy
Bagaimana saya bisa melakukan sesuatu yang mirip dengan perintah terakhir Anda di bash? Saya menggunakan bash 3.3 dan mencoba untuk mengkompensasi kekuranganreadarray -d
user1156544
3

Versi kalengan dari jawaban @ 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
...

The local -akan membuat pilihan seperti set -f( noglob) lokal untuk fungsi, seperti variabel.

The declare -n a=$1akan menciptakan lokal variabel asebagai alias untuk variabel global yang disebut oleh $1(argumen pertama ke fungsi).

mosvy
sumber