Kann mir jemand die Option -C von mapfile genauer erklären?

1 Antwort

Ein Callback ist einfach eine Funktion, die automatisch aufgerufen wird, wenn ein bestimmtes Ereignis eintritt – in diesem Fall jedes Mal, wenn "mapfile" eine neue Zeile liest.

Der Callback von mapfile ermöglicht es dir so, für jede Zeile, die eingelesen wird, eine Funktion (der Callback) aufzurufen. Diese Funktion kannst du verwenden, um die Zeilen zu bearbeiten oder eine andere Art der Verarbeitung durchzuführen.

Nehmen wir mal ein kleines Beispiel

callback() {
  echo "${1//,/ }"
}

mapfile -C callback ABC.csv

Was passiert hier?

  • Jede Zeile der CSV-Datei wird eingelesen.
  • Die Callback-Funktion wird aufgerufen und ersetzt die Kommas durch Leerzeichen.
  • Die veränderte Zeile wird ausgegeben

A65HN 
Beitragsersteller
 22.01.2025, 10:02

Perfekt, das hilft mir sogar in mehr als einer Hinsicht weiter:

  1. Die Schreibweise zum Ändern einer Zeile kannte ich noch nicht (bisher habe ich dafür immer sed eingespannt)
  2. Um die Semikola (deutsche locale der csv) loszuwerden, habe ich bisher bei mapfile immer die Option -t verwendet. Aber deine callback-function kann dazu verwendet werden, den newline am Ende jeder Zeile loszuwerden. Das hat mich bei der Ausgabe des letzten array-Index immer ein wenig gestört, und so hattte ich die csv-Datei ein wenig modifiziert: sed -i 's/$/;/' csv-Datei

Danke für den Tipp. 👍

A65HN 
Beitragsersteller
 22.01.2025, 12:02
@A65HN

Leider zu früh gefreut:

$ cat nachstellen.sh
#!/bin/bash
callback() {
  echo "${1//,/ }"
}

mapfile -C callback ABC.csv
$
$ cat ABC.csv
Name,Vorname,Alter
Meier,Sven,33
Müller,Volker,47
Schulze,Frieder,63
$
$ source nachstellen.sh
bash: mapfile: »ABC.csv«: Ist kein gültiger Bezeichner.
$

Dann habe ich das Skript ein wenig modifiziert:

$ cat nachstellen.sh
#!/bin/bash
callback() {
  echo "${1//,/ }"
}

mapfile -C callback var < ABC.csv
$
$ source nachstellen.sh
$
$ echo ${var[@]}
Name,Vorname,Alter Meier,Sven,33 Müller,Volker,47 Schulze,Frieder,63
$

Ergebnis: es wird nur newline in ein Leerzeichen umgewandelt, was mapfile aber schon von Haus aus macht. Die function bewirkt im Zusammenhang mit der Option -C also nichts. Oder habe ich bei deinem Beispiel etwas falsch verstanden?

anTTraXX  22.01.2025, 12:15
@A65HN

Besuche mal

#!/bin/bash
callback() {
  processed_lines+=("${1//,/ }") 
}


processed_lines=()
mapfile -C callback var < ABC.csv


# Optional: Die Ergebnisse der Verarbeitung ausgeben
echo "${processed_lines[@]}"
A65HN 
Beitragsersteller
 22.01.2025, 13:25
@anTTraXX

Leider keine Änderung:

$ echo ${var[@]}

$ echo "${processed_lines[@]}"

$ source nachstellen.sh
$ echo ${var[@]}
Name,Vorname,Alter Meier,Sven,33 Müller,Volker,47 Schulze,Frieder,63
$
$ echo "${processed_lines[@]}"

$

Dann habe ich bei mapfile noch die Option -d',' mit hinzugenommen:

$ unset var
$ unset processed_lines
$ source nachstellen.sh
$ echo ${var[@]}
Name, Vorname, Alter Meier, Sven, 33 Müller, Volker, 47 Schulze, Frieder, 63
$ echo "${processed_lines[@]}"

$

Da wird dann das Komma nicht getauscht, sondern es wird zusätzlich zum Komma ein Leerzeichen hinzugefügt. Das ist aber auch nachvollziehbar, weil dann das Komma als Trenner verwendet wird. Am Ende der Zeile bleibt nach wie vor nur das schon ohne Option -C erzeugte Leerzeichen stehen.