web-dev-qa-db-ja.com

区切り文字を使用しているときにreadarrayによって追加された新しい行を削除するにはどうすればよいですか?

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?最新の$記号の意味は何ですか?

9
user1156544

暗黙的な末尾の改行文字は、組み込みのreadarrayではなくnotですが、bashのhere-string(<<<)によって追加されます。 bash here-stringが末尾の改行文字を追加するのはなぜですか?printfを使用して改行なしで文字列を出力し、プロセス置換手法< <()を介してそれを読み取ることで、これを取り除くことができます。

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

今は正しく生成されます

declare -a ARR=([0]="a" [1]="b" [2]="c" [3]="d")
12
Inian

Split + globを使用できます(リストコンテキストで展開を引用符で囲まないままにするとどうなりますか)。それはほとんどの場合私たちの邪魔になります、私たちが実際にそれを必要とするときにそれを使用しないのは残念です:

IFS=,
set -o noglob

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

これは、一時ファイルを作成してreadarray <<< "$string"のアプローチのようにreadarrayを呼び出すよりも少し複雑です(readarray -dには、bashの最新バージョンが必要です)。

S内のIFSseparatorを表す)にも関わらず、a,,b,"a"""に分割されている点でreadarrayと同じように機能します。 "b"のみ。

実際の分割演算子の場合は、代わりにzshを使用できます。

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

(空の要素を保持するための@および二重引用符)。

4

@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 -fnoglob)などのオプションを、変数と同様に、関数に対してローカルにします。

declare -n a=$1は、_local変数aを、$1(関数の最初の引数)で指定されたグローバル変数のエイリアスとして作成します。

3
mosvy