Comandes LinuxLinuxVeure el contingut d'un fitxer a Linux

Manipular text a la línia de comandes: cut, sort, uniq, tr i companyia

GNU textutils proporciona


Una de les grans virtuts de la línia de comandes de Linux és que pots tractar text amb petites eines que fan una sola cosa i es combinen amb canonades (|): una talla columnes, una altra ordena, una altra compta… Amb quatre o cinc d’aquestes eines pots analitzar un registre, netejar un CSV o fer un informe ràpid sense obrir cap programa.

Què eren les GNU textutils

Les GNU textutils eren el paquet del projecte GNU amb les eines per tractar fitxers de text: cat, cut, sort, uniq, wc, tr, head, tail, paste, join, nl, split… L’any 2003 es van fusionar amb les fileutils i les sh-utils en un sol paquet, les GNU coreutils, que és el que trobes avui a qualsevol distribució. Les eines són les mateixes; només ha canviat el nom del paquet.

La versió anterior d’aquest article hi incloïa grep, sed i awk. Són eines igual d’imprescindibles, però no han format mai part de les textutils: cadascuna és un paquet GNU independent. Les veuràs també aquí, perquè es fan servir juntes contínuament.

Fitxer d’exemple

$ cat persones.csv
nom,ciutat,edat
joan,Girona,34
maria,Lleida,28
pere,Girona,45
anna,Reus,28

cat: mostrar i unir fitxers

cat fitxer1.txt fitxer2.txt > resultat.txt

Tens els detalls a la comanda cat. Les seves companyes per veure trossos d’un fitxer són head (el principi), tail (el final) i tac (a l’inrevés).

cut: extreure columnes

Amb -d indiques el separador i amb -f els camps que vols:

$ cut -d, -f1,3 persones.csv
nom,edat
joan,34
maria,28
pere,45
anna,28

També pots tallar per posició de caràcter amb -c (cut -c1-4). cut només accepta un separador d’un sol caràcter i no sap tractar diversos espais seguits com un de sol: per a sortides alineades amb espais, és millor awk '{print $2}'.

sort: ordenar

sort fitxer.txt           # alfabèticament
sort -r fitxer.txt        # a l'inrevés
sort -n fitxer.txt        # numèricament
sort -u fitxer.txt        # ordena i treu les línies repetides
sort -h fitxer.txt        # mides «humanes» (1K, 2M, 3G)

Per ordenar per una columna, indica el separador amb -t i la columna amb -k. Aquí, per edat de més gran a més petita, sense la capçalera:

$ tail -n +2 persones.csv | sort -t, -k3,3nr
pere,Girona,45
joan,Girona,34
anna,Reus,28
maria,Lleida,28

-k3,3 vol dir «de la columna 3 a la 3». Si només poses -k3, sort agafa des de la columna 3 fins al final de la línia.

uniq: línies repetides

uniq només detecta repeticions consecutives, per això gairebé sempre va darrere de sort:

sort fitxer.txt | uniq        # treu duplicats (com sort -u)
sort fitxer.txt | uniq -c     # compta quantes vegades surt cada línia
sort fitxer.txt | uniq -d     # només les línies repetides
sort fitxer.txt | uniq -u     # només les que surten una vegada

La combinació sort | uniq -c | sort -rn és un clàssic per fer rànquings. Quantes persones hi ha de cada ciutat:

$ tail -n +2 persones.csv | cut -d, -f2 | sort | uniq -c | sort -rn
      2 Girona
      1 Reus
      1 Lleida

wc: comptar

$ wc persones.csv
 5  5 75 persones.csv

Línies, paraules i bytes. Per a una sola cosa: wc -l (línies), wc -w (paraules), wc -c (bytes) o wc -m (caràcters, que no és el mateix que bytes si hi ha accents).

tr: canviar o esborrar caràcters

echo "Hola" | tr 'a-z' 'A-Z'           # a majúscules
echo "a   b    c" | tr -s ' '          # redueix espais repetits a un
tr -d '\r' < windows.txt > linux.txt   # treu els retorns de carro de Windows

Quedar-se només amb els números:

$ echo "telèfon: 972-12-34-56" | tr -d -c '0-9\n'
972123456

Compte: tr treballa byte a byte, i no entén les lletres accentuades. echo "Hola Món" | tr 'a-z' 'A-Z' dona HOLA MóN. Per a text amb accents, fes servir GNU sed: sed 's/.*/\U&/' dona HOLA MÓN.

paste, join i comm: combinar fitxers

paste posa fitxers un al costat de l’altre:

$ paste -d, noms.txt edats.txt
joan,34
maria,28

Amb -s posa totes les línies d’un fitxer en una de sola:

$ paste -sd, noms.txt
joan,maria

join uneix dos fitxers pel camp que tenen en comú (com un JOIN de bases de dades). Tots dos han d’estar ordenats per aquest camp:

$ cat usuaris.txt
1 joan
2 maria
$ cat ciutats.txt
1 Girona
2 Lleida
$ join usuaris.txt ciutats.txt
1 joan Girona
2 maria Lleida

comm compara dos fitxers ordenats i et diu què és només al primer, només al segon o a tots dos. Amb -12 mostra només les línies comunes:

comm -12 <(sort llista1.txt) <(sort llista2.txt)

nl i split

nl numera les línies (com cat -n, però per defecte no numera les buides):

nl fitxer.txt

split divideix un fitxer gran en trossos, per línies (-l) o per mida (-b):

split -l 1000 registre.log tros_      # tros_aa, tros_ab…
split -b 100M copia.tar.gz copia_     # per enviar-lo en parts
cat copia_* > copia.tar.gz            # per tornar-lo a unir

Les companyes: grep, sed i awk

grep busca línies que contenen un patró. Tens una guia completa a l’article sobre grep.

grep "Girona" persones.csv
grep -c "Girona" persones.csv      # quantes línies
grep -v "^#" config.conf           # treu els comentaris

sed és un editor de flux: modifica el text a mesura que passa. L’ús més comú és substituir:

sed 's/antic/nou/g' fitxer.txt          # mostra el resultat, no toca el fitxer
sed -i 's/antic/nou/g' fitxer.txt       # modifica el fitxer
sed -i.bak 's/antic/nou/g' fitxer.txt   # modifica'l i en desa una còpia .bak
sed -n '2,3p' fitxer.txt                # només les línies 2 i 3
sed '/^pere/d' persones.csv             # esborra les línies que comencen per «pere»

awk treballa per columnes i pot fer càlculs. Multiplicar per 2 la primera columna, o sumar les edats:

awk '{print $1 * 2}' numeros.txt
awk -F, 'NR > 1 {suma += $3} END {print suma}' persones.csv

En tens molts més exemples a la guia d’awk.

Combinar-les

La força d’aquestes eines és encadenar-les. Unes quantes receptes:

Les 10 IP que fan més peticions a un servidor web:

cut -d' ' -f1 /var/log/apache2/access.log | sort | uniq -c | sort -rn | head

Els noms (primera columna) de les persones de Girona, ordenats i sense repeticions:

grep "Girona" persones.csv | cut -d, -f1 | sort -u

Els 10 fitxers més grans d’un directori:

du -ah /var/log | sort -rh | head

Les paraules més freqüents d’un text:

tr -s '[:space:]' '\n' < text.txt | sort | uniq -c | sort -rn | head

Compte amb…

  • No redirigeixis al mateix fitxer que llegeixes. sort fitxer.txt > fitxer.txt el buida abans de llegir-lo. Fes servir un fitxer temporal o, amb sort, l’opció -o: sort -o fitxer.txt fitxer.txt.
  • L’idioma afecta l’ordre. sort ordena segons la configuració regional (LANG), i el resultat pot canviar d’un sistema a un altre. Als scripts, si necessites un ordre estable, fes servir LC_ALL=C sort.
  • Els CSV de debò són més complicats. Si un camp pot contenir comes entre cometes ("Girona, Catalunya"), cut i awk -F, fallaran. Per a aquests casos, fes servir una eina que entengui CSV (per exemple, csvkit o mlr, del paquet miller).

Comandes relacionades