Wie entferne ich eine neue Zeile, die durch Readarray hinzugefügt wurde, wenn ein Trennzeichen verwendet wird?

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

Ergebnis:

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

Wie kann ich sagen readarray, dass die letzte Zeile nicht hinzugefügt werden soll \n? Was bedeutet das neueste $Symbol?

user1156544
quelle

Antworten:

12

Das implizite nachgestellte Zeichen für neue Zeilen wird nicht durch das readarrayeingebaute Zeichen, sondern durch die Zeichenfolge here-string ( <<<) von hinzugefügt. bashSiehe Warum fügt eine Bash-Zeichenfolge hier ein Zeichen für nachfolgende Zeilenumbrüche hinzu? . Sie können dies beseitigen, indem Sie die Zeichenfolge ohne die neue Zeile drucken printfund über eine Prozesssubstitutionstechnik lesen< <()

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

würde jetzt richtig generieren

declare -a ARR=([0]="a" [1]="b" [2]="c" [3]="d")
Inian
quelle
3
Wow! Ich hätte das nie gefunden. Danke
user1156544
4

Sie können split + glob verwenden (was passiert, wenn Sie eine Erweiterung in Listenkontexten nicht in Anführungszeichen setzen). Es steht uns die meiste Zeit im Weg, es wäre eine Schande, es nicht zu benutzen, wenn wir es tatsächlich brauchen:

IFS=,
set -o noglob

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

Das ist etwas weniger kompliziert als das Schreiben einer temporären Datei und das anschließende Aufrufen readarraywie im readarray <<< "$string"Ansatz (beachten Sie auch, dass readarray -deine sehr aktuelle Version von erforderlich ist bash).

Beachten Sie, dass trotz der Sin IFS(das steht für Separator ), dass die gleiche Art und Weise wie funktioniert readarray, dass a,,b,ist aufgeteilt in "a", ""und"b" nur.

Für einen echten Aufteilungsoperator können Sie zshstattdessen Folgendes verwenden :

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

(die @und doppelte Anführungszeichen, um die leeren Elemente zu erhalten).

Stéphane Chazelas
quelle
Das readarray <<< "$string"schreibt in eine temporäre Datei und löscht sie dann, anstatt den Speicher zu verwenden?
user1156544
@ user1156544 Ja.
Mosvy
Wie kann ich etwas Ähnliches wie Ihren letzten Befehl in Bash tun? Ich benutze Bash 3.3 und versuche, den Mangel anreadarray -d
user1156544
3

Eine Dosenversion der Antwort von @ 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
...

Das local -macht Optionen wie set -f( noglob) lokal für die Funktion, genau wie Variablen.

Das declare -n a=$1erstellt eine lokale Variable aals Alias ​​für die globale Variable mit dem Namen $1(das erste Argument für die Funktion).

Mosvy
quelle