Как удалить новую строку, добавленную readarray при использовании разделителя?

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

Результат:

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

Как я могу сказать, readarrayчтобы не добавлять заключительный перевод строки \n? В чем смысл последнего $символа?

user1156544
источник

Ответы:

13

Неявный завершающий символ новой строки добавляется неreadarray встроенной функцией, а функцией here-string ( <<<) bash, см. Почему bash here-string добавляет завершающий символ новой строки? , Вы можете избавиться от этого, напечатав строку без использования новой строки, printfи прочитав ее по методике подстановки процесса< <()

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

будет правильно генерировать сейчас

declare -a ARR=([0]="a" [1]="b" [2]="c" [3]="d")
Inian
источник
3
Вот Это Да! Я бы никогда не нашел это. Спасибо
user1156544
4

Вы можете использовать split + glob (что происходит, когда вы оставляете расширение без кавычек в списках). Это мешает нам большую часть времени, было бы стыдно не использовать его, когда нам это действительно нужно:

IFS=,
set -o noglob

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

Это немного менее запутанно, чем запись временного файла и последующее обращение readarrayк нему, как в readarray <<< "$string"подходе (также обратите внимание, что readarray -dнужна очень свежая версия bash).

Обратите внимание, что, несмотря на Sin IFS(который обозначает разделитель ), он работает так же, как и readarrayв этом a,,b,, разделен на "a", ""и "b"только.

Для реального оператора расщепления вы можете использовать zshвместо:

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

( @и двойные кавычки для сохранения пустых элементов).

Стефан Шазелас
источник
readarray <<< "$string"Пишет в файл tempp , а затем удаляет его вместо того , чтобы использовать память?
user1156544
@ user1156544 Да.
Мосви
Как я могу сделать что-то похожее на вашу последнюю команду в bash? Я использую Bash 3.3 и пытаюсь компенсировать отсутствиеreadarray -d
user1156544
3

Консервированная версия ответа @ 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 -Сделает варианты , как set -f( noglob) локальные функции, так же , как переменные.

declare -n a=$1Создаст локальную переменную в aкачестве псевдонима к глобальной переменной с именем на $1(первый аргумент функции).

mosvy
источник