Perl, a „praktikus kinyerési és jelentésnyelv” (Practical Extraction and Report Language) nevéhez hűen, kiválóan alkalmas szöveges adatok feldolgozására, manipulálására és rendezésére. Gyakran adódik feladatként, hogy egy szövegfájl sorai elé sorszámot illesszünk. Legyen szó logfájlok elemzéséről, konfigurációs fájlok áttekintéséről, programkódok hibakereséséről vagy egyszerűen csak a jobb olvashatóság érdekében, a sorok megszámozása felbecsülhetetlen értékű lehet. Különösen praktikus, ha a sorszám fix, kétkarakteres formátumú, például `01`, `02`, egészen `99`-ig. Ez a formátum megkönnyíti az adatok vizuális szkennelését és az egységes megjelenést. Ebben a cikkben részletesen bemutatjuk, hogyan valósítható meg ez a feladat Perl segítségével, különböző megközelítéseket és praktikus tippeket adva.
Miért Pont Kétkarakteres Sorszámozás? 🤔
A kétkarakteres sorszám, mint a `01`, `02`, egészen `99`-ig, számos előnnyel jár. Először is, vizuálisan rendezettebbé teszi a listát. A számok azonos szélességűek, ami megakadályozza a sorok „ugrálását” a dokumentum böngészése közben, mint ahogy azt a `1`, `2`, `10`, `100` formátum okozhatja. Másodszor, szabványos formátumot biztosít kisebb fájlok vagy kódrészletek esetén, ahol a sorok száma ritkán haladja meg a 99-et. Harmadszor, bizonyos adatexportálási vagy jelentési igényeknél, ahol fix oszlopszélességre van szükség, ez a megközelítés ideális.
Az Alapok: Sorszámozás Standard Bemenetről Standard Kimenetre (STDIN/STDOUT) 🚀
Kezdjük a legegyszerűbb esettel: beolvasunk a standard bemenetről, és a sorszámozott eredményt kiírjuk a standard kimenetre. Ez a megközelítés ideális parancssori eszközökkel, például `cat` vagy `pipe` segítségével történő kombinálásra.
Perlben minden egyes beolvasott sorhoz tartozik egy speciális változó, a `$.`, ami az aktuális sor sorszámát tárolja. Ez a változó automatikusan növekszik, ahogy a Perl egy új sort dolgoz fel. Ahhoz, hogy kétkarakteres, vezető nullás formátumot kapjunk, a `sprintf` függvényt használhatjuk.
perl -pe '$_ = sprintf("%02d ", $.) . $_'
Elemezzük ezt az egyetlen soros kódot:
* `perl`: Meghívjuk a Perl értelmezőt.
* `-p`: Ez a kapcsoló azt mondja a Perlnek, hogy ismételje meg a programot minden bemeneti sorra. Ezenkívül minden sor után automatikusan kiírja a `$_` változó tartalmát.
* `-e`: Ezzel a kapcsolóval a parancssorból adhatunk meg egy rövid szkriptet.
* `sprintf(„%02d „, $.)`: Ez a rész formázza a sor sorszámát.
* `%02d`: Ez a formátumspecifikátor azt jelenti, hogy egy decimális (egész) számot (`d`) szeretnénk, melynek hossza legalább két karakter (`2`). Ha a szám egyjegyű (pl. `1`), akkor a `0` jelzi, hogy vezető nullával (`0`) kell kitölteni a két karakteres hosszt. Például az 1-ből `01`, a 10-ből `10` lesz.
* `$.`: A Perl beépített változója, ami az aktuális bemeneti sor sorszámát tartalmazza.
* `. $_`: A `.` operátorral hozzáfűzzük a formázott sorszámot az aktuális sor tartalmához (ami a `$_` változóban található).
**Példa használatra:**
Tegyük fel, hogy van egy `lista.txt` fájlunk a következő tartalommal:
„`
Alma
Körte
Szilva
Barack
„`
Futtassuk a parancsot:
`cat lista.txt | perl -pe ‘$_ = sprintf(„%02d „, $.) . $_’`
**Kimenet:**
„`
01 Alma
02 Körte
03 Szilva
04 Barack
„`
Ez a módszer rendkívül gyors és hatékony kisebb, egyszeri feladatokhoz.
Részletesebb Megközelítés: Szkript Fájlban 📝
Bár az egy soros parancs remekül működik, bonyolultabb logika vagy jobb olvashatóság esetén érdemesebb egy külön Perl szkript fájlt létrehozni. Ez lehetőséget ad a kommentálásra, hibakezelésre és további funkciók hozzáadására.
Hozzunk létre egy `sorszamozas.pl` nevű fájlt:
„`perl
#!/usr/bin/perl
use strict;
use warnings;
while (my $sor =
# Az aktuális sor sorszáma ($.) automatikusan növekszik
# A sprintf-fel formázzuk a sorszámot kétjegyűre, vezető nullával
my $sorszamozott_sor = sprintf(„%02d „, $.) . $sor;
print $sorszamozott_sor;
}
„`
**Magyarázat:**
* `#!/usr/bin/perl`: Shebang sor, ami megmondja a rendszernek, hogy Perl értelmezővel futtassa a szkriptet.
* `use strict; use warnings;`: Ezek a modulok alapvető fontosságúak a jó programozási gyakorlat szempontjából. Segítenek az esetleges hibák korai felismerésében és megelőzésében.
* `while (my $sor =
* `my $sorszamozott_sor = sprintf(„%02d „, $.) . $sor;`: Ez ugyanaz a logikai művelet, mint az egy soros parancsban, csak egy külön változóba mentjük az eredményt a jobb olvashatóság érdekében.
* `print $sorszamozott_sor;`: Kiírjuk a sorszámozott sort a standard kimenetre.
**Futtatás:**
`cat lista.txt | perl sorszamozas.pl`
Vagy
`perl sorszamozas.pl < lista.txt`
A kimenet azonos lesz az előző példával. Ez a megközelítés sokkal rugalmasabb, ha a jövőben bővíteni szeretnénk a szkriptet, például bizonyos sorok kihagyásával, feltételes sorszámozással, vagy akár egyedi előtagok hozzáadásával.
Fájlok Közvetlen Kezelése: Beolvasás és Mentés 💾
Gyakran nem csak a standard bemenettel dolgozunk, hanem közvetlenül egy vagy több fájl tartalmát kell sorszámozni, és az eredményt egy másik fájlba vagy akár vissza az eredeti fájlba írni.
1. Fájl Beolvasása és Új Fájlba Mentése
Ez a legbiztonságosabb módszer, mivel az eredeti fájl változatlan marad.
„`perl
#!/usr/bin/perl
use strict;
use warnings;
# Ellenőrizzük, hogy legalább két argumentumot kaptunk-e: bemeneti és kimeneti fájl
unless (@ARGV == 2) {
die „Használat: perl sorszamozas_fajlba.pl
}
my $bemeneti_fajl = shift @ARGV; # Az első argumentum a bemeneti fájl
my $kimeneti_fajl = shift @ARGV; # A második argumentum a kimeneti fájl
# Megnyitjuk a bemeneti fájlt olvasásra
open(my $bemenet, ‘<', $bemeneti_fajl)
or die "Nem nyitható meg a bemeneti fájl '$bemeneti_fajl': $!";
# Megnyitjuk a kimeneti fájlt írásra. Ha létezik, felülírja.
open(my $kimenet, '>‘, $kimeneti_fajl)
or die „Nem nyitható meg a kimeneti fájl ‘$kimeneti_fajl’: $!”;
# A Perl sorszám ($.) automatikusan nullázódik, amikor fájlt nyitunk olvasásra,
# így az első sor az 1-es sorszámot kapja.
while (my $sor = <$bemenet>) {
# Formázás és írás a kimeneti fájlba
printf $kimenet „%02d %s”, $., $sor;
}
# Bezárjuk a fájlokat
close $bemenet;
close $kimenet;
print „Sikeresen sorszámozva: ‘$bemeneti_fajl’ -> ‘$kimeneti_fajl’n”;
„`
**Futtatás:**
`perl sorszamozas_fajlba.pl bemenet.txt kimenet.txt`
2. Helyben Szerkesztés (In-Place Editing) a `-i` Kapcsolóval ⚠️
A Perl rendkívül erőteljes funkciója a `-i` kapcsoló, amely lehetővé teszi a fájlok helyben történő módosítását. Ez azt jelenti, hogy a kimenet közvetlenül felülírja az eredeti fájlt. Ezt óvatosan kell használni, de rendkívül hatékony lehet. Mindig ajánlott biztonsági másolatot készíteni!
**Biztonsági másolattal:**
„`
perl -i.bak -pe ‘$_ = sprintf(„%02d „, $.) . $_’ lista.txt
„`
Ez a parancs sorszámozza a `lista.txt` fájlt, és létrehoz egy `lista.txt.bak` nevű biztonsági másolatot az eredeti tartalommal. Az `-i.bak` paraméter azt mondja a Perlnek, hogy minden módosított fájlról készítsen egy `.bak` kiterjesztésű biztonsági másolatot.
**Biztonsági másolat nélkül (Fokozott Óvatosság!):**
„`
perl -i -pe ‘$_ = sprintf(„%02d „, $.) . $_’ lista.txt
„`
Ez a parancs közvetlenül felülírja a `lista.txt` fájlt az új, sorszámozott tartalommal, biztonsági másolat készítése nélkül. **Csak akkor használd, ha biztos vagy benne, hogy nincs szükséged az eredeti fájlra, vagy ha előzőleg manuálisan készítettél másolatot!**
Túl a 99 Sorszámon: Háromjegyű és Többjegyű Sorszámok 💯
Mi történik, ha egy fájlban több mint 99 sor található? A `%02d` formátum ekkor már nem lesz elegendő, hiszen a `100` például csak `100` lesz, nem `0100`. Ha azt szeretnénk, hogy a formázás egységes maradjon, akkor a formátumspecifikátort kell módosítani.
Ha maximum 999 sorra számítunk, használhatjuk a `%03d`-t:
„`perl
perl -pe ‘$_ = sprintf(„%03d „, $.) . $_’ lista.txt
„`
Ez a `1`-ből `001`-et, a `10`-ből `010`-et, a `100`-ból `100`-at csinál. Általánosságban, ha `N` számjegyre van szükségünk, akkor `%0Nd` formátumot kell használni.
További Finomhangolások és Tippek ✨
* **Egyedi Elválasztó Karakter:** A sorszám utáni szóköz helyett bármilyen más karaktert vagy karakterláncot használhatunk:
„`perl
perl -pe ‘$_ = sprintf(„[%02d] – „, $.) . $_’ lista.txt
„`
Eredmény: `[01] – Alma`
* **Üres Sorok Kezelése:** Alapértelmezés szerint a Perl minden sort sorszámoz, beleértve az üreseket is. Ha ki szeretnénk hagyni az üres sorokat a sorszámozásból, akkor egy feltételt kell hozzáadni:
„`perl
perl -pe ‘if ($. =~ /^s*$/) { $_ = $_ } else { $_ = sprintf(„%02d „, $.) . $_ }’ lista.txt
# Vagy egyszerűbben:
# perl -pe ‘$_ = (length(chomp($_)) > 0 ? sprintf(„%02d „, $.) : „”) . $_ . „n”‘ lista.txt
# Ez utóbbi bonyolultabb, mivel a chomp() a $_-t módosítja, és utána kell újra sorvéget tenni.
# Egy jobb megoldás üres sorok kihagyására, sorszám kihagyásával:
# my $counter = 0; perl -ne ‘print (length($_) > 1 ? sprintf(„%02d „, ++$counter) . $_ : $_)’ lista.txt
„`
Ez utóbbi esetben a `$.` már nem felel meg, mert az a bemeneti sorok száma, nem a sorszámozott sorok száma. Egy külön számlálót kell bevezetni, ahogy a fenti példa is mutatja (`$counter`).
* **Több Fájl Sorszámozása:** Ha több fájlt adunk meg a parancssorban (pl. `perl -pe … file1.txt file2.txt`), a Perl automatikusan újraindítja a `$.` számlálót minden egyes fájl feldolgozásakor, így mindegyik fájl 1-től fog sorszámozódni. Ha egy *folyamatos* sorszámozásra van szükség az összes fájlra kiterjedően, akkor a szkriptben kell ezt kezelni, és a `$.` helyett egy saját számlálót kell használni, amit nem resetelünk.
* **Unicode/UTF-8 fájlok:** Amennyiben a szövegfájl Unicode karaktereket tartalmaz, fontos lehet a megfelelő kódolás kezelése. Ezt a `use open` pragma segítségével tehetjük meg:
„`perl
#!/usr/bin/perl
use strict;
use warnings;
use utf8; # A szkript maga is UTF-8
use open qw(:std :utf8); # Standard I/O (stdin, stdout, stderr) UTF-8-ként kezelése
while (my $sor =
my $sorszamozott_sor = sprintf(„%02d „, $.) . $sor;
print $sorszamozott_sor;
}
„`
Ez biztosítja, hogy a Perl helyesen értelmezze és kezelje a nem-ASCII karaktereket.
Véleményem és Tapasztalataim 💡
A Perl, mint text-processing eszköz, már a `90-es évek` vége óta, az informatikai karrierem kezdetétől hű társam. Sokszor szembesültem olyan problémákkal, ahol nagyméretű logfájlokat, exportált adatbázis-tartalmakat vagy éppen konfigurációs fájlokat kellett gyorsan áttekinthetővé tenni. Egy alkalommal egy több százezer soros Apache logfájlban kerestem egy nagyon specifikus hibát. A logok nem voltak sorszámozva, ami rendkívül megnehezítette az azonosítást és a kollégákkal való kommunikációt („nézd meg a 34567-es sor körül”). Ekkor vetettem be először a Perl `-i.bak -pe ‘$_ = sprintf(„%07d „, $.) . $_’` parancsot, mert tudtam, hogy a log mérete meghaladja a tízezer sort is.
A logfájl gyors sorszámozása nemcsak a hiba lokalizálásában segített, hanem a csapatmunka hatékonyságát is nagymértékben növelte. Azóta a sorszámozás az egyik első lépés, amit megteszek, ha strukturálatlan szöveges adatokkal kell dolgoznom, amiben rendet szeretnék látni. Ez a kis trükk rengeteg időt és fejfájást spórolt meg nekem.
Összegzés és Következtetés 🔚
A Perl rendkívül hatékony és rugalmas eszköz a szöveges adatok manipulálására, és a sorok automatikus sorszámozása csak egy apró szelete annak, amire képes. A `$.` változó és a `sprintf` függvény kombinációja elegáns és erőteljes megoldást nyújt a fix szélességű, vezető nullás sorszámok beillesztésére. Legyen szó parancssori gyors megoldásról vagy egy komplexebb szkriptről, a Perl biztosítja az ehhez szükséges eszközöket.
Emlékezzünk mindig a jó gyakorlatokra: használjunk `use strict; use warnings;`, és legyünk óvatosak a fájlok helyben történő módosításakor (`-i` kapcsoló), különösen, ha nincs biztonsági másolat. A szöveges adatok feldolgozása terén a Perl egy igazi svájci bicska, amelynek elsajátítása hatalmas előnyt jelenthet a mindennapi feladatok során. Kísérletezzünk bátran, és fedezzük fel a benne rejlő lehetőségeket!