- awk este un instrument și un limbaj de scripting orientat spre procesarea textului pe linii și coloane, ideal pentru filtrarea, transformarea și analizarea ieșirilor... comenzi și fișiere.
- Vă permite să definiți modele și acțiuni prin combinarea expresiilor regulate, variabilelor speciale precum $0, $1, NF sau NR și funcțiilor precum length, substr sau match pentru a crea filtre foarte precise.
- awk funcționează confortabil cu delimitatori și câmpuri folosind FS, OFS și opțiuni precum -F și poate format ieșiri cu print și printf, efectuarea de operații matematice și gestionarea variabilelor cu -v.
- Este posibil să se creeze scripturi awk complete care automatizează sarcini complexe, inclusiv căutări și înlocuiri cu gsub, calcule avansate și generarea de rapoarte din comenzi precum ps, df sau fișiere de sistem.
Când începi să iei consola în serios Linux Descoperi că lucrul cu text nu înseamnă doar vizualizarea fișierelor cu cat Și cam asta e tot. De îndată ce intri în busteni Pentru liste uriașe de procese, ieșiri de comenzi sau fișiere CSV, ai nevoie de ceva mult mai puternic pentru a filtra, transforma și rezuma datele fără a te înnebuni.
Aici intervine awk.o comandă care, mai mult decât un simplu filtru, este practic un limbaj de de programare Awk este un instrument de procesare a textului care vă permite să căutați modele, să selectați coloane, să efectuați calcule, să definiți condiții, să utilizați variabile, bucle, funcții și chiar să scrieți scripturi complete. În acest tutorial awk pentru Linux, îl vom explora pas cu pas, de la elementele de bază până la utilizări destul de avansate, încorporând tot felul de exemple de consolă din lumea reală.
Ce este awk și la ce se folosește în Linux?
Awk este atât un instrument de linie de comandă, cât și un limbaj de scripting Conceput pentru a analiza text structurat în linii și câmpuri, numele său provine de la inițialele creatorilor săi (Aho, Weinberger și Kernighan). Este utilizat de la sfârșitul anilor 70, dar rămâne o componentă cheie în orice mediu. Unix sau GNU/Linux (de exemplu, pentru Rulați vechiul Unix pe PC-ul dvs.).
Filosofia lui awk este foarte simplăIterează un fișier (sau rezultatul unei comenzi) linie cu linie, împarte fiecare linie în coloane conform unui separator, verifică dacă o condiție este îndeplinită și, dacă da, execută o acțiune. Dacă nu specificați o condiție, acțiunea se aplică tuturor liniilor; dacă nu specificați o acțiune, acțiunea implicită este afișarea întregii linii.
Cu acest mecanism simplu, poți face lucruri cu adevărat scandaloase.: din afișarea doar a unor coloane ale ps o df...la calcularea totalurilor, filtrarea după modele complexe cu expresii regulate, înlocuirea textului, formatarea rapoartelor, lucrul cu fișiere CSV sau chiar scrierea de scripturi de câteva zeci de linii.
Deși awk s-ar putea să vă amintească puțin de grep sau sedAbordarea sa este mai structurată: gândiți-vă la linii ca la înregistrări și la cuvinte (sau câmpuri) ca la coloane, cu variabile interne și un mini-limbaj care îl face ideal pentru procesarea rapidă a datelor tabelare.
În practică, dacă vrei să începi să scrii scripturi shell adecvate...Este aproape obligatoriu să știi awk împreună cu alte utilitare precum sed, grep, cut și companie. Acestea sunt elementele de bază ale procesării de text în Linux.
Instalați și rulați awk (gawk) pe sistemul dvs.
În majoritatea distribuțiilor GNU/Linux moderneawk este deja instalat în mod implicit, de obicei în varianta GNU awk (gawkPuteți verifica cu:
awk --version
Dacă, dintr-un anumit motiv, nu îl aveți instalatÎn Debian, Ubuntu și derivate puteți utiliza managerul de pachete:
sudo apt update && sudo apt install gawk
Este disponibil și pe macOS.Puteți utiliza versiunea de sistem sau puteți instala o versiune actualizată cu Homebrew:
brew install gawk
Odată instalat, awk este folosit întotdeauna cu aceeași idee.Transmiteți instrucțiuni între ghilimele simple și un fișier (sau transmiteți rezultatul unei alte comenzi prin pipe). De exemplu:
awk '{print}' archivo.txt
De asemenea, poți folosi awk ca interpretor de scripturi, indicând calea către executabil în prima linie a fișierului:
#!/usr/bin/awk -f
și apoi rularea scenariu direct sau cu awk -f script.awk.
Sintaxă de bază: modele și acțiuni

Structura minimală a lui awk este:
awk 'patrón { acción }' fichero
Fiecare linie a fișierului este comparată cu modelul.Dacă se potrivește, se execută acțiunea dintre acolade. Dacă omiteți modelul, acțiunea se aplică tuturor liniilor. Câteva idei cheie:
Variabile speciale pentru referire la fiecare linie:
$0: linia completă.$1, $2, $3, …: câmpuri (coloane) ale liniei, separate prin delimitatorul definit.NF: numărul de câmpuri din linia curentă.NR: numărul de înmatriculare curent (numărul liniei globale).FNR: numărul liniei din fișierul curent, util la procesarea mai multor fișiere.
Instrucțiuni speciale:
BEGIN { … }: bloc care se execută înainte de citirea oricărei linii.END { … }: bloc care se execută după procesarea tuturor liniilor.
Cele mai comune comenzi de ieșire:
print: afișează argumentele separate de separatorul de ieșire (OFS(implicit, un spațiu).printfsimilar cuprintfÎn C, permite formatarea detaliată fără a adăuga automate sfârșituri de linie.
Exemplu minimal pentru imprimarea unui fișier exact așa cum este, ca și cum ar fi cat:
awk '{print}' archivo.txt
Sau dacă doriți să afișeze și lungimea fiecărei linii:
awk '{print length, "\t", $0}' archivo.txt
Lucrul cu coloane și separatoare în awk
Una dintre utilizările principale ale awk este manipularea coloanelor. din ieșirile comenzilor, cum ar fi ps, df sau fișiere precum /etc/passwdÎn mod implicit, awk consideră orice spațiu sau tabulator ca separator, dar puteți utiliza practic orice delimitator.
Selectați coloane specifice
Imaginează-ți ieșirea din ps cu mai multe coloane (PID, TTY, TIME, CMD…)Dacă vrei să vezi doar PID-urile, pur și simplu:
ps | awk '{print $1}'
Dacă sunteți interesat de a doua coloană (de exemplu, TTY):
ps | awk '{print $2}'
Și dacă vrei să sari peste prima linie (antetul)Puteți filtra după numărul de înregistrare:
ps | awk 'NR>1 {print $1}'
Ideea este foarte simplă.: fiecare număr după simbol $ Se referă la coloana corespunzătoare, întotdeauna în raport cu separatorul curent.
Schimbați delimitatorul cu -F și cu FS
Multe fișiere de sistem nu sunt separate prin spații.dar de alții simboluriUn clasic este /etc/passwdunde câmpurile sunt separate de :Pentru a procesa acel fișier pe coloane, aveți două opțiuni: opțiunea -F pe linia de comandă sau variabila FS în interiorul unui bloc BEGIN.
Utilizarea comenzii -F în linia de comandă:
cat /etc/passwd | awk -F ":" '{print $1}'
Acest exemplu afișează doar nume de utilizator (primul câmp) deoarece separatorul este acum :Dacă doriți și UID-ul și GID-ul (câmpurile 3 și 4), pur și simplu:
cat /etc/passwd | awk -F ":" '{print $1, $3, $4}'
Problema cu această comandă este că ieșirea este blocată. Dacă nu definiți separatori expliciți, puteți adăuga spații sau tabulatori manual:
cat /etc/passwd | awk -F ":" '{print $1 " " $3 " " $4}'
Dacă doriți un rezultat mai tabelarputeți folosi \t pentru a insera tabulatori:
cat /etc/passwd | awk -F ":" '{print $1 "\t" $3 "\t" $4}'
Alternativa cu FS într-un bloc BEGIN Îți permite să setezi separatorul chiar în scriptul awk:
cat /etc/passwd | awk 'BEGIN { FS=":" } {print $1 "\t" $3 "\t" $4}'
Ambele abordări sunt echivalente din punct de vedere funcționaldeși folosește BEGIN {FS=...} De obicei, este mai curat atunci când scrii scripturi .awk reutilizabile.
FS și OFS: separatoare de intrare și ieșire
Pe lângă FS (Field Separator), awk are OFS (Output Field Separator)care definește modul în care câmpurile sunt separate atunci când utilizați print cu virgule:
cat /etc/passwd | awk 'BEGIN { FS=":"; OFS=" - " } {print $1, $3, $4}'
În acest caz, citești cu : dar scrii cu - , generând o ieșire de genul:
root - 0 - 0
daemon - 1 - 1
...
Această combinație FS/OFS este foarte utilă pentru „reformatarea” datelorDe exemplu, pentru a converti dintr-un format în altul sau pentru a pregăti ieșiri lizibile pe care le exportați apoi într-un alt sistem.
Obține ultimul câmp cu $NF (și pe cele anterioare)
În multe ieșiri de comandăCâmpul care te interesează este la sfârșit, dar numărul exact de coloane variază. Acolo $NF (Numărul de câmpuri) vă simplifică viața: este întotdeauna ultimul câmp din linia curentă.
De exemplu, în /etc/shells Căile shell valide apar la sfârșitul fiecărei liniiUneori în a doua coloană, alteori în a treia etc. Pentru a afișa doar numele shell-ului (partea de după ultima bară oblică):
awk -F "/" '/^\// {print $NF}' /etc/shells
Dacă doriți apoi să păstrați doar valori unice (fără duplicate), puteți înlănțui cu uniq:
awk -F "/" '/^\// {print $NF}' /etc/shells | uniq
Și dacă ceea ce te interesează este penultimul element al căii (de exemplu, directorul anterior), puteți utiliza $(NF-1) o $(NF-2):
awk -F "/" '/^\// {print $(NF-1)}' /etc/shells
awk -F "/" '/^\// {print $(NF-2)}' /etc/shells
Filtrarea liniilor cu modele, lungime și condiții logice
Awk este excelent atunci când vrei să te limitezi doar la anumite rânduri. bazate pe modele de text, coloane specifice sau condiții numerice. Combinați expresii regulate, operatori logici și funcții precum length pentru a realiza filtre foarte precise.
Filtrare după modele și expresii regulate
Cea mai directă metodă de a filtra după conținut este de a plasa expresia regulată între bare oblice. Chiar înainte de chei:
awk '/patrón/ {print}' archivo.txt
De exemplu, odată cu plecarea lui df Puteți afișa doar linii care încep cu o bară oblică (sisteme de fișiere montate):
df | awk '/^\// {print}'
Dacă doriți o anumită partiție, de exemplu /dev/sda5:
df | awk '/^\/dev\/sda5/ {print}'
De asemenea, puteți filtra după modele la începutul sau sfârșitul liniei utilizând ^ y $:
awk '/^tmpfs/ {print}' archivo.txt
awk '/\/shm$/ {print}' archivo.txt
Și combină mai multe criterii cu operatorul logic &&De exemplu, liniile care încep cu tmpfs și se termină în /dev/shm:
df | awk '/\/shm$/ && /^tmpfs/ {print}'
Filtrați după coloane și afișați doar ceea ce vă interesează
Adesea doriți să filtrați nu doar rândurile, ci și coloanele.Continuând cu df -h, puteți afișa doar sisteme de fișiere reale (^/) și apoi păstrați coloanele 1, 2 și 3:
df -h | awk '/^\// {print $1 "\t" $2 "\t" $3}'
Awk vă permite chiar să lucrați cu câmpuri din mersDe exemplu, adăugați coloanele 2 și 3 (utilizată + disponibilă) pentru a vedea o „capacitate totală” calculată:
df -h | awk '/^\// {print $1 "\t" $2 + $3}'
Dacă doriți să adăugați unitatea literală „G” la sfârșitul rezultatului:
df -h | awk '/^\// {print $1 "\t" $2 + $3 "G"}'
Filtrați după lungimea liniei folosind length()
Funcția length() măsoară numărul de caractere dintr-un șir de caractereSe folosește în mod normal cu $0 (linie întreagă), dar îl puteți folosi și cu o anumită coloană.
Pentru a afișa doar liniile de /etc/shells cu mai mult de 9 caractere:
awk 'length($0) > 9' /etc/shells
Dacă vrei să vezi lungimea fiecărei linii:
awk '{print length, "\t", $0}' /etc/shells
De asemenea, puteți filtra după lungime și apoi puteți imprima doar lungimea.:
awk 'length($0) > 9 {print length}' /etc/shells
Combinați mai multe condiții cu && și dacă
Pe lângă utilizarea expresiilor regulate la începutPuteți scrie condiții complete în cadrul blocului folosind if, comparație și operatori logici.
De exemplu, afișând doar linii de df -h care încep cu t și a cărui coloană 6 are mai mult de 8 caractere:
df -h | awk '/^t/ && length($6) > 8 {print $0}'
Un alt caz tipic este căutarea proceselor după ultimul câmp (comandă executată) la ieșirea din ps -efUltimul câmp este $NFDeci poți folosi:
ps -ef | awk '{ if ($NF == "firefox") print $0 }'
Dacă vă interesează doar PID-ul și comanda:
ps -ef | awk '{ if ($NF == "firefox") print $2, $NF }'
Linii de control cu NR, intervale și lungimea câmpului
Variabila NR (Număr de înregistrări) Numără câte linii au fost citite până acum (la nivel global). Aceasta permite acțiuni comune precum omiterea anteturilor, afișarea anumitor intervale de linii sau afișarea doar a primului rând.
Numără liniile și afișează doar prima sau a doua
Pentru a număra numărul total de linii dintr-un fișier fara a folosi wc -l Poți face:
awk 'END {print NR}' archivo.txt
Dacă doriți să imprimați doar prima linie:
awk 'NR==1 {print}' archivo.txt
Și pentru a afișa doar a doua linie:
awk 'NR==2 {print}' archivo.txt
Imprimare începând de la o anumită linie sau interval
Pentru a afișa toate liniile de la a treia încolo Poți folosi o condiție simplă cu > o >=:
ps -aux | awk 'NR>2 {print}'
Dacă doriți un interval, de exemplu liniile 2 până la 4 en /etc/shells:
cat /etc/shells | awk 'NR==2, NR==4 {print $0}'
De asemenea, puteți imprima numărul liniei lângă conținut:
cat /etc/shells | awk 'NR==2, NR==4 {print NR, $0}'
Lungimea anumitor câmpuri
Pe lângă măsurarea lungimii liniilor completePuteți verifica lungimea unei anumite coloane. De exemplu, pentru a vedea câte caractere are sistemul de fișiere (coloana 1) în rezultatul df -h:
df -h | awk '{print length($1) "\t" $1}'
Dacă doriți să săriți peste antet (prima linie), adaugă NR>1:
df -h | awk 'NR>1 {print length($1) "\t" $1}'
Funcții utile: substr, match, RSTART și RLENGTH
Awk include o gamă bună de funcții textDouă dintre cele mai puternice metode pentru căutări avansate sunt substr y match, aceasta din urmă însoțită de variabilele RSTART y RLENGTH.
Acoperă textul cu substr()
Funcția substr(cadena, inicio) o substr(cadena, inicio, longitud) Vă permite să extrageți subșiruri. De exemplu, pentru a elimina primele 5 caractere de pe fiecare linie de /etc/shells:
cat /etc/shells | awk '{print substr($0, 5)}'
Dacă nu doriți să procesați prima linie (de exemplu, un comentariu), puteți utiliza NR:
cat /etc/shells | awk 'NR>1 {print substr($0, 5)}'
Rețineți că primul parametru este șirul de caractere (de obicei $0) iar al doilea indică ce caracter doriți să începeți să afișați.
Localizarea modelelor cu match(), RSTART și RLENGTH
Funcția match(cadena, /regex/) căutarea unei expresii regulate în șirDacă se găsește o potrivire, returnează poziția inițială (bazată pe 1) și populează două variabile:
RSTART: poziția unde începe modelul găsit.RLENGTH: durata meciului.
De exemplu, pentru toate liniile de ps -aux care conțin „cpu”Puteți afișa întreaga linie și poziția în care se află modelul:
ps -aux | awk 'match($0, /cpu/) {print $0 " Contiene \"cpu\" en la posición " RSTART}'
Dacă doriți să știți și dimensiunile modelului găsit, folosește doar RLENGTH la ieșire:
ps -aux | awk 'match($0, /cpu/) {print $0 " Posición=" RSTART " Longitud=" RLENGTH}'
Acest tip de căutare este utilizat pe scară largă în analiza textului și bioinformaticăDe exemplu, în fișierele FASTA, unde sunteți interesat să localizați motive specifice în secvențe.
Operații matematice și variabile în awk
Awk nu se limitează la afișarea textului: vă permite să efectuați operații numerice direct asupra câmpurilor, variabilelor interne sau valorilor pe care le transmiteți din linia de comandă sau din mediul shell.
Definiți variabilele cu -vy și folosiți-le în BEGIN
Puteți declara variabile cu opțiunea -v când se invocă awkDe exemplu, înmulțirea a două numere fixe:
awk -v a="10" -v b="20" 'BEGIN {print "La multiplicación de a x b es", a*b}'
De asemenea, este posibil să transmiteți valori variabile din shell-ul dvs.Dacă în bash faci:
a=1.5
b=4
Apoi le poți folosi în awk astfel::
awk -v a="$a" -v b="$b" 'BEGIN {print "La multiplicación de a x b es", a*b}'
Blocul BEGIN este folosit aici deoarece nu procesăm niciun fișier.Vrem doar să rulăm cod o singură dată și să afișăm un rezultat.
Funcții matematice: sqrt și bucle for
Awk încorporează mai multe funcții matematice standard.Ca sqrt() pentru rădăcini pătrate. De exemplu, rădăcina pătrată a lui 400:
awk 'BEGIN {print sqrt(400)}'
De asemenea, îl puteți combina cu buclele for pentru a genera liste complete:
awk 'BEGIN { for(i=1; i<=10; i++) print "La raíz cuadrada de", i*i, "es", i }'
Sau parcurgeți valorile zecimale de la 0 la 1 în trepte mici:
awk 'BEGIN { for(i=0; i<=1; i=i+0.00001) print "La raíz cuadrada de", i*i, "es", i }'
Aceste tipuri de structuri fac ca awk să fie foarte similar cu un limbaj tradițional.deși habitatul său natural rămâne formatul de coloană.
Scrierea și rularea scripturilor complete în awk
Când comenzile awk încep să devină lungi Dacă doriți să reutilizați transformări complexe, lucrul mai înțelept de făcut este să le salvați într-un fișier script cu extensia . .awk (deși nu este obligatoriu).
Un exemplu tipic implică procesarea rezultatului df pentru a afișa doar anumite intrări care îndeplinesc condițiile privind spațiul disponibil și pentru a formata rezultatele ca un tabel mic.
Imaginează-ți că vrei următoarele:
- Afișează doar sistemele de fișiere al căror nume începe cu „t” (de exemplu
tmpfs). - Filtrați-le pe cele cu o capacitate disponibilă (coloana 4) mai mare de 6000K.
- Tipăriți doar unitatea (coloana 1) și suma coloanelor 2 și 3 ca un spațiu total aproximativ.
Puteți crea un script numit capacidad.awk cu conținut similar cu acesta (adaptat și simplificat):
#!/usr/bin/awk -f
BEGIN { printf "%s\n", "Voy a extraer las partes que me interesan del comando df" }
BEGIN { printf "%s\t%s\n", "Unidad", "Capacidad disponible" }
/^t/ && $4 > 6000 {print $1 "\t" $2 + $3 "K"}
Și apoi executați-l prin înlănțuirea ieșirii lui df.:
df | awk -f capacidad.awk
Dacă doriți să îmbunătățiți aspectul mesei, puteți înlocui print de printf și folosiți formate precum %-12s (text aliniat la stânga în 12 caractere) sau %-23d (Număr zecimal în 23 de caractere). Aceasta vă oferă control perfect asupra alinierii coloanelor.
Găsește și înlocuiește text cu gsub()
Awk poate efectua, de asemenea, înlocuiri de text similar cu ceea ce ați face cu sed, folosind funcția gsub() (înlocuitor global).
Sintaxa generală este:
gsub("texto_o_regex_a_buscar", "texto_de_reemplazo", destino)
De exemplu, să presupunem un fișier geekland.txt cu textul „Geekland este cel mai bun blog de tehnologie” și vrei să schimbi inițiala G în g:
awk '{ gsub("G", "g", $0); print $0 }' geekland.txt
Dacă nu specificați al treilea parametru, căutarea se efectuează pe $0 în mod implicitTotuși, este foarte obișnuit să se limiteze înlocuirea la o singură coloană:
df -h | awk '{ gsub("M", "G", $2); print $2 }'
În acest caz, am schimbat unitatea M în G doar în coloana 2.Dacă doriți să afișați și coloana 1 aliniată corect, o puteți combina cu printf:
df -h | awk '{ gsub("M", "G", $2); printf "%-12s %-12s\n", $1, $2 }'
Acest model „Modific o coloană și apoi o imprim formatată” Este extrem de util în rapoarte, migrări de date sau curățări rapide ale ieșirii comenzilor.
Utilizări suplimentare: pisică infectată cu steroizi și executarea comenzilor
Deși poate părea o prostieawk poate acționa ca cat Îmbunătățit, deoarece poate afișa un fișier în timp ce adaugă informații suplimentare (numere de linie, lungimi etc.).
O utilizare banală ar fi:
awk '{print}' functions.php
Dar poți, de asemenea, numerota linii sau aplica orice filtru. fără a fi nevoie să folosiți niciun instrument suplimentar.
Un alt fapt interesant este că awk poate executa comenzi de sistem dupa functie system()De exemplu, pentru a afișa directorul curent:
awk 'BEGIN { system("pwd") }'
Aceasta nu este cea mai obișnuită practică în scripturile simple.Dar e bine de știut că există atunci când construiești instrumente mai complexe bazate pe awk.
Awk devine un briceag elvețian pentru text în LinuxÎți permite să filtrezi rânduri, să selectezi și să combini coloane, să înlocuiești fragmente, să măsori lungimi, să localizezi modele, să însumezi câmpuri, să generezi rapoarte cu formate mici și chiar să construiești scripturi complete care procesează rezultatul altor comenzi. Odată ce te obișnuiești cu el, devine un instrument esențial ori de câte ori lucrezi cu... terminal și date structurate.
Scriitor pasionat despre lumea octeților și a tehnologiei în general. Îmi place să îmi împărtășesc cunoștințele prin scriere și asta voi face în acest blog, să vă arăt toate cele mai interesante lucruri despre gadgeturi, software, hardware, tendințe tehnologice și multe altele. Scopul meu este să vă ajut să navigați în lumea digitală într-un mod simplu și distractiv.