Het is vrij eenvoudig om de inhoud van een Linux tekstbestand gelezen regel voor regel in een shell script, zolang je om met enkele subtiele valkuilen. Hier is hoe het de veilige manier te doen.
Files, Tekst en Idioms
Elke programmeertaal heeft een set van idioom. Dit zijn de standaard, no-nonsense manieren om een reeks gemeenschappelijke taken uit te voeren. Ze zijn de basis- of standaard manier om een van de kenmerken van de taal van de programmeur is het werken met te gebruiken. Ze worden een deel van toolkit van mentale blauwdrukken van een programmeur.
Acties zoals het lezen van gegevens uit bestanden, het werken met loops, en het omwisselen van de waarden van twee variabelen zijn goede voorbeelden. De programmeur zal ten minste een manier om hun eindigt in een generieke of vanille-mode te bereiken weten. Misschien dat zal volstaan voor de eis bij de hand. Of misschien zullen ze de code verfraaien het efficiënter of van toepassing zijn op de specifieke oplossing die zij ontwikkelen om te maken. Maar het hebben van de bouwsteen idioom bij de hand is een goed uitgangspunt.
Kennen en begrijpen uitdrukkingen in één taal maakt het makkelijker op te halen een nieuwe programmeertaal, ook. Weten hoe de dingen zijn opgebouwd in één taal en op zoek naar de equivalente of het dichtste ding in een andere taal is een goede manier om de overeenkomsten en verschillen tussen programmeertalen die je al kent en degene waarmee u nu leren waarderen.
Het lezen van regels uit een bestand: De One-Liner
In Bash, kunt u gebruik maken van een
terwijl
lus op de opdrachtregel om elke regel van de tekst uit een bestand te lezen en er iets mee doen. Onze tekstbestand heet “data.txt.” Het houdt een lijst van de maanden van het jaar.
JANUARI februari maart . . oktober November December
Onze eenvoudige one-liner is:
terwijl leeslijn; do echo $ lijn; done & lt; data.txt
De
terwijl
lus leest een lijn van het bestand en de uitvoeringsstroom van de kleine programma over op het lichaam van de lus. De
echo
opdracht schrijft de lijn van de tekst in het terminal-venster. De lees poging mislukt als er geen regels meer te lezen, en de lus wordt gedaan.
Een handige truc is het vermogen een bestand omleiden in een lus . In andere programmeertalen, zou je nodig hebt om het bestand te lezen uit deze te openen en weer dicht als je klaar was. Met Bash, kunt u gewoon gebruik maken van file redirection en laat de komgreep al die low-level stuff voor u.
Natuurlijk, deze one-liner is niet erg handig. Linux biedt al de
kat
commando, dat precies dat voor ons doet. We hebben een lange adem weg naar een drie-letter commando vervangen gecreëerd. Maar het doet zichtbaar tonen de principes van het lezen van een bestand.
Dat werkt goed genoeg, tot op zekere hoogte. Stel we hebben nog een tekstbestand dat de namen van de maanden bevat. In dit bestand is de escape sequentie voor een nieuwe regel wordt toegevoegd aan elke regel. We noemen het “data2.txt.”
januari \ n Februari \ n Maart \ n . . Oktober \ n November \ n December \ n
Laten we gebruik maken van onze one-liner op onze nieuw bestand.
terwijl leeslijn; do echo $ lijn; done & lt; data2.txt
De backslash escape character”
\
”Werd weggegooid. Het resultaat is dat een “n” werd toegevoegd aan elke regel. Bash is de interpretatie van de backslash als het begin van een
escape
. Vaak willen we niet Bash om te interpreteren wat hij leest. Het kan handiger zijn om een lijn in zijn geheel-backslash escape sequences en lees alle-en kiezen wat te ontleden of te vervangen jezelf, in je eigen code.
Als we willen een zinvolle verwerking of parsing doen op de lijnen van tekst, zullen we nodig hebben om een script te gebruiken.
Het lezen van regels uit een bestand met een Script
Hier is onze script. Het heet “script1.sh.”
#! / Bin / bash
Counter = 0
terwijl IFS = lees -r LinefromFile [116 ] || [[ -n " $ {LinefromFile} " ] ], doen
(( Teller ++ ))
echo "openen leiding $ Teller $ {LinefromFile} " [9 ]
gedaan & lt; " $ 1 "
We stellen een variabele met de naam
Balie
naar nul, dan definiëren we onze
terwijl
lus.
De eerste verklaring over de while lijn
IFS = ''
.
IFS
staat voor interne veidscheider. Het houdt waarden die Bash gebruikt om woordgrenzen te identificeren. Standaard wordt de leescommando strips uit voorste en achterste witruimte. Willen we de lijnen uit het bestand precies zoals ze zijn gelezen, moeten we set
IFS
een lege string.
We zouden dit keer buiten de lus te stellen, net zoals we de waarde van zijn instelling
Balie
. Maar met meer complexe scripts-vooral die met veel door de gebruiker gedefinieerde functies in hen, is het mogelijk dat
IFS
zou elders in het script worden ingesteld op verschillende waarden. Verzekeren dat
IFS
is ingesteld op een lege tekenreeks elke keer dat de
terwijl
lus herhaalt garandeert dat we weten wat het gedrag zal zijn.
We gaan een regel tekst te lezen in een variabele met de naam
Linefromfile
. We gebruiken de
-R
(Lees backslash als een normale character) optie om backslashes te negeren. Ze zullen worden behandeld, net als elk ander teken en zal een speciale behandeling krijgen.
Er zijn twee voorwaarden die zal voldoen aan de
terwijl
lus en laat de tekst te verwerken door het lichaam van de lus:
-
lees -r LinefromFile: Wanneer een regel tekst met succes wordt gelezen uit het bestand, hoelezencommando stuurt een succes signaal naar deterwijl, en deterwijllus passeert de uitvoeringsstroom aan het lichaam van de lus. Merk op dat delezencommando moet een zien nieuwe regel aan het eind van de lijn van de tekst in om er een actie succesvol te overwegen. Als het bestand is geen POSIX compliant tekstbestand, de laatste regel mag niet zijn voorzien van een nieuwe regel . Als delezencommando ziet de einde van het bestand marker (EOF) voor de regel wordt beëindigd door een nieuwe regel, zal het niet behandelen als een succesvol lezen. Als dat gebeurt, zal de laatste tekstregel niet worden doorgegeven aan het lichaam van de lus zal niet worden verwerkt. -
[-N "$ {LinefromFile}"]: We moeten wat extra werk niet-POSIX compatibele bestanden handle te doen. Deze vergelijking controleert de tekst die wordt gelezen uit het bestand. Als het niet wordt beëindigd met een nieuwe regel karakter, zal deze vergelijking nog steeds succes aan de terugkeerterwijllus. Dit zorgt ervoor dat elke lijn achter fragmenten worden verwerkt door het lichaam van de lus.
Deze twee clausules worden gescheiden door de OR logische operator”
||
”Zodat als
of
clausule rendement succes wordt de opgehaalde tekst verwerkt door het lichaam van de lus, of er een nieuwe regel of niet.
In het lichaam van onze lus, we zijn het verhogen van de
Balie
variabele een en gebruik
echo
enkele uitgang naar de terminal venster te sturen. De lijn en de tekst van elke lijn worden weergegeven.
We kunnen nog steeds gebruik maken van onze redirection truc om een bestand te sturen naar een lus. In dit geval, we ombuigen van $ 1, een variabele die de naam van de eerste command line parameter die doorgegeven aan het script houdt. Met behulp van deze truc, kunnen we gemakkelijk passeren in de naam van het bestand dat we willen het script aan te werken.
Kopieer en plak het script in een editor en sla het op met de bestandsnaam “script1.sh.” Gebruik de
chmod
opdracht
om het uitvoerbaar te maken
.
chmod + x script1.sh
Laten we eens kijken wat onze script maakt van de data2.txt tekstbestand en de backslashes die het bevat.
./ script1.sh data2.txt
Elk personage in de regel wordt letterlijk. De backslashes worden niet geïnterpreteerd als escape-tekens. Ze zijn afgedrukt als gewone karakters.
Het passeren van de lijn naar een functie
We zijn nog steeds gewoon weergave van de tekst naar het scherm. In een real-world programmeercenario zouden we waarschijnlijk iets interessants doen met de lijn van tekst. In de meeste gevallen is het een goede programmeringspraktijk om de verdere verwerking van de lijn in een andere functie aan te pakken.
Dit is hoe we het kunnen doen. Dit is "Script2.SH."
We definiëren onze
Balie
variabele als voorheen, en dan definiëren we een functie genaamd
Process_line ()
. De definitie van een functie moet verschijnen
voordat
De functie wordt eerst het script genoemd.
Onze functie wordt doorgegeven aan de nieuw leeslijn van tekst in elke iteratie van de
terwijl
lus. We hebben toegang tot die waarde binnen de functie met behulp van de
$ 1
variabele. Als er twee variabelen waren doorgegeven aan de functie, hebben we toegang tot die waarden met behulp van
$ 1
en
$ 2
, enzovoort voor meer variabelen.
De w
hile
Loop is voornamelijk hetzelfde. Er is maar één verandering in het lichaam van de lus. De
echo
lijn is vervangen door een oproep aan de
Process_line ()
functie. Merk op dat u de "()" haakjes niet hoeft te gebruiken in de naam van de functie wanneer u het belt.
De naam van de variabele die de tekstlijn vasthoudt,
Linefromfile
, is gewikkeld in aanhalingstekens wanneer deze wordt doorgegeven aan de functie. Dit is geschikt voor lijnen die spaties erin hebben. Zonder de aanhalingstekens wordt het eerste woord behandeld als
$ 1
Door de functie wordt het tweede woord beschouwd als te zijn
$ 2
, enzovoort. Het gebruik van aanhalingstekens zorgt ervoor dat de volledige regel tekst wordt afgehandeld, helemaal als
$ 1
. Merk op dat dit is
niet
hetzelfde
$ 1
Dat geldt hetzelfde gegevensbestand dat is doorgegeven aan het script.
Omdat
Balie
is verklaard in het hoofdgedeelte van het script en niet in een functie, kan worden verwezen in de
Process_line ()
functie.
Kopieer of typ het script hierboven in een editor en sla deze op met de bestandsnaam "Script2.SH." Maak het uitvoerbaar
chmod
:
CHMOD + X Script2.SH
Nu kunnen we het uitvoeren en een nieuw gegevensbestand doorgeven, "Data3.txt." Dit heeft een lijst met de maanden erin, en één regel met veel woorden erop.
JANUARI februari maart . . oktober November \ Nmore tekst "aan het einde van de lijn" December
Onze opdracht is:
./ Script2.Sh Data3.txt
De lijnen worden uit het bestand gelezen en passeerden één voor één naar de
Process_line ()
functie. Alle regels worden correct weergegeven, inclusief de vreemde met de backspace, aanhalingstekens en meerdere woorden erin.
Bouwstenen zijn nuttig
Er is een gedachtegang die zegt dat een idioom iets unieks voor die taal moet bevatten. Dat is geen overtuiging dat ik me abonneer. Wat belangrijk is, is dat het goed gebruik maakt van de taal, is gemakkelijk te onthouden en biedt een betrouwbare en robuuste manier om een functionaliteit in uw code te implementeren.