Ce face mapfile / readarray
mapfile (cu numele alternativ readarray) citește intrarea standard și pune fiecare rând într-un element de tablou. Este mai scurt și mai rapid decât o buclă while read și păstrează corect spațiile din rânduri.
Opțiunea -t elimină caracterul de rând nou de la finalul fiecărui element; aproape întotdeauna o vrei. Pentru ieșirea unei comenzi folosește substituția de proces < <(comandă), nu un pipe: comandă | mapfile rulează mapfile într-un subshell, iar tabloul se pierde.
mapfile există din Bash 4.0. Pe macOS, Bash-ul implicit este 3.2, unde se folosește bucla while IFS= read -r din ultimul exemplu.
Opțiuni și argumente
| Opțiune / Parametru | Descriere |
|---|---|
-t |
Elimină rândul nou de la finalul fiecărui element. |
-s N |
Sare peste primele N rânduri (de exemplu antetul unui CSV). |
-n N |
Citește cel mult N rânduri. |
-d DELIM |
Folosește alt separator în loc de rând nou (Bash 4.4+); -d '' pentru ieșirea lui find -print0. |
-O INDEX |
Începe să scrie în tablou de la indexul dat. |
Exemple
Exemplul 1: Rândurile unui fișier într-un tablou
Fiecare elev devine un element; cu -t, elementele nu mai conțin rândul nou.
printf '%s\n' "Ana" "Mihai" "Ioana" > elevi.txt
mapfile -t elevi < elevi.txt
echo "Număr elevi: ${#elevi[@]}"
echo "Al doilea elev: ${elevi[1]}"
Ieșire în terminal
Număr elevi: 3
Al doilea elev: Mihai
Exemplul 2: Un CSV fără antet
-s 1 sare peste rândul de antet, iar expansiunea parametrilor desparte numele de notă.
cat > note.csv <<'EOF'
nume,nota
Ana,9
Mihai,7
Ioana,10
EOF
mapfile -t -s 1 randuri < note.csv
for rand in "${randuri[@]}"; do
echo "${rand%%,*} are nota ${rand#*,}"
done
Ieșire în terminal
Ana are nota 9
Mihai are nota 7
Ioana are nota 10
Exemplul 3: Alternativa pentru Bash 3.2 și sh
Bucla while IFS= read -r face același lucru pe sistemele fără mapfile. IFS= păstrează spațiile, iar -r păstrează backslash-urile.
printf '%s\n' "Ana Pop" "Mihai Ionescu" > elevi.txt
elevi=()
while IFS= read -r linie; do
elevi+=("$linie")
done < elevi.txt
echo "Număr elevi: ${#elevi[@]}"
echo "Primul elev: ${elevi[0]}"
Rezultat
Număr elevi: 2
Primul elev: Ana Pop
Greșeli frecvente
cat fisier | mapfile -t linii: tabloul se umple în subshell-ul pipe-ului și este gol după acest rând. Scriemapfile -t linii < fisiersau< <(comanda).- Uitarea lui
-t: fiecare element se termină cu un rând nou, iar comparațiile de tipul[ "${linii[0]}" = Ana ]eșuează. - Folosirea lui
mapfileîntr-un script cu#!/bin/shsau pe Bash 3.2 (macOS): comanda nu există.
Comenzi înrudite
Tablouri în Bash (indexate și asociative): Liste de valori accesate prin index (tablou[0]) și dicționare cheie-valoare cu declare -A, cu parcurgere și numărare.read: Citește o linie de text de la tastatură sau din intrarea standard și o salvează într-o variabilă.while: Execută repetat un bloc de comenzi atâta timp cât condiția specificată rămâne adevărată.Redirecționare și conducte (Pipes): Redirecționarea fluxurilor standard de intrare (stdin), ieșire (stdout), erori (stderr) și legarea prin conducte (pipes).