Grep en sed Demystified

Grep. Je hoort het vaak. Je ziet die cryptische IT-kerels die het commando typen, systeembeheerders noemen het terloops, je ziet het zelfs in sommige shellscripts. Het lijkt een van die dingen die gewoon bestaat, maar niet voor jou is bedoeld. Dit artikel zal dat veranderen - we zullen Grep (en de minder bekende vriend sed) in dit nieuwste deel van OS X Demystified uitleggen en snel een kijkje nemen..


Invoering

grep

Grep is een opdrachtregelprogramma voor het zoeken en filteren van een soort tekstuele invoer op basis van parameters die u invoert

Grep is een opdrachtregelprogramma voor het zoeken en filteren van een soort tekstuele invoer op basis van parameters die u invoert. Met andere woorden, het draait in de Terminal (Toepassingen → Hulpprogramma's → Terminal) en wordt uitsluitend gebruikt door opdrachten te typen. Er zijn natuurlijk GUI-wrappers die een beetje meehelpen, maar geen enkele is zo krachtig of veelzijdig als het gebruik van de commandoregel voor onbewerkte bestanden, dus daar zullen we ons op concentreren.

Dat is allemaal leuk, maar wat doet het eigenlijk? Klinkt het bovenstaande te vaag? Hier is een voorbeeld. Stel dat je een tekstblok hebt in een bestand met de naam jungle.txt met vijf regels:

Een leeuw slaapt in de jungle Een leeuw slaapt vannacht Een tijger ontwaakt in het moeras De papegaai observeert Wimoweh, wimoweh, wimoweh, wimoweh

Om de regel te vinden die het woord tijger bevat, gebruiken we grep als volgt:

grep tiger jungle.txt

Het resultaat dat we krijgen is:

"Een tijger ontwaakt in het moeras"

Ok, dat is duidelijk, toch? Laten we een stap terug doen.

Grep opwaarderen

Zoals blijkt, is Mac grep langzamer dan GNU grep, dus laten we eerst een upgrade uitvoeren. Om een ​​snellere grep te installeren, voert u het volgende in Terminal in en drukt u op invoeren:

brouwinstallatie https://raw.github.com/Homebrew/homebrew-dupes/master/grep.rb

Houd er rekening mee dat je Homebrew hebt geïnstalleerd om dit te kunnen doen en om te weten te komen hoe je Homebrew kunt installeren, zie mijn vorige artikel.

Een breed scala aan geeklets zal vaak op grep vertrouwen om gegevens van grote tekstbestanden of geoogste websites op te halen

Wat hebben we bereikt door deze upgrade uit te voeren? Welnu, veel apps gebruiken de geïnstalleerde native grep-tool om te functioneren. Een breed scala aan geeklets zal bijvoorbeeld vaak op grep vertrouwen om gegevens op te halen van grote tekstbestanden of geoogste websites. Dus, allemaal je grep-gebruikende geeklets zullen nu verschillende keren sneller zijn in hun greppy-delen. Bovendien moet u soms een soort foutenlogboek bij de hand houden (stel dat u een enorm foutenlogboek van een toepassing hebt en de ondersteuningsdienst van de app zegt dat u deze "grep port-1723" moet plakken). Als het logboek miljoenen regels code bevat, kunt u veel tijd besparen met deze veel snellere grep.

Zodra Homebrew je nieuwe grep installeert, probeer je het volgende als je de bestanden hebt gemaakt. Zo niet, ga je gang en maak ze, voer dan de opdracht uit om te controleren of alles werkt.

grep tiger jungle.txt

Sed

Sed is een stream editor. Botweg gezegd, het kost input, bewerkt het en voert de bewerkte inhoud uit. Of het nu in een bestand wordt bewerkt of direct vanuit Terminal wordt gevoed, is helemaal niet relevant voor sed - het heeft één zeer geavanceerde en configureerbare functie en voert het zo goed mogelijk uit.

Sed neemt wat tekstinvoer, een commando over hoe het te veranderen, en produceert gewijzigde uitvoer

Dus waar wordt sed gebruikt? Het bewerken van bestandsinhoud en dergelijke, natuurlijk, maar het gebeurt zo dat het feilloos hand in hand met Grep werkt. Laten we eerst een aantal zuivere sed-voorbeelden bekijken. Typ het volgende in Terminal:

echo "Hallo"

en druk op enter. De terminal zegt hallo. Typ nu

echo "Hallo" | sed 's / Hell / Heaven /'

en druk op enter. Je zou "Heaveno" moeten zien. Wat is er zojuist gebeurd? Zie, sed werkt door twee argumenten te nemen. De eerste is de feed, de invoer en de tweede is een string (je kunt zien dat het een tekenreeks is omdat deze is geciteerd), die vertelt welke acties moeten worden uitgevoerd op het eerste argument. In ons geval is dat:

  • s (vervanging)
  • / (scheidingsteken - in ons geval schuine streep, zie volgende paragraaf voor alternatieven)
  • Hell (reguliere expressiepatroon om te zoeken naar)
  • Heaven (vervangende reeks)

Het tweede lijstitem vermeldt alternatieven voor het scheidingsteken voorwaartse slash; soms komen ze erg van pas omdat ze bijvoorbeeld URL's of bestandspaden moeten schrijven. Neem bijvoorbeeld de URL myfolder / mysubfolder / myfile. Als we dit in sed zetten om het te vervangen myotherfolder / myotherfile, de parameter zou er zo uitzien: s / myfolder / mysubfolder / myfile / myotherfolder / myotherfile / dat is gewoon een grote zak onzin - sed kan onmogelijk weten welke van die fragmenten de regexp is en welke de vervangende string is. Daarom zouden we dat moeten doen ontsnappen de forwardslashes in ons bestand met backslash, zodat elke forwardslash in het pad zou veranderen \ /. Ik vermoed dat je het probleem kunt zien. De nieuwe parameter sed ziet er als volgt uit:

sed 's / mijnmap \ / mijnsubmap \ / mijnbestand / mijnandere mappen \ / mijnandere bestand /'

Dit nauwelijks leesbare formaat wordt een "piketomheining" genoemd en om dit te voorkomen ondersteunt sed verschillende scheidingstekens zoals onderstrepingsteken (_), dubbele punt (:) en pipe (|). Als we bijvoorbeeld het pipe-teken als scheidingsteken zouden gebruiken, zouden we het volgende krijgen:

sed 's | myfolder / mysubfolder / myfile | myotherfolder / myotherfile |'

Veel beter, nee?

Een ander ding echter. We zeiden dat sed twee argumenten aanvoert, maar we geven er slechts één - direct na de sed commando. Dit komt door het pijppersonage na ons echo commando. De pijp dient als een middel om de uitvoer van de linker operand naar de invoer van de rechter operand te leiden. In ons geval vertelde het pijproken karakter het sed programma "Neem als input wat het ook is dat je krijgt van wat er aan de linkerkant van me is". sed heeft geen idee dat het te maken heeft met echo - het hoeft niet te weten. Het enige dat het weet is dat het tekstinvoer heeft. Het bespreken van de pijplijn in meer detail dan deze valt buiten het bestek van dit artikel, maar voel je vrij om te lezen als je geïnteresseerd bent.

De pijp dient als een middel om de uitvoer van de linker operand naar de invoer van de rechter operand te leiden.

Dus hoe combineren we het met grep? Het is precies hetzelfde. Als we ons vorige voorbeeld nemen, laten we het volgende in de terminal invoeren.

grep tiger jungle.txt | sed 's / moeras / woestijn /'

en we krijgen de uitvoer

"Een tijger ontwaakt in de woestijn"

Laten we nu eens kijken naar een geval uit de echte wereld.


Real World-toepassing

Voor onze "dissectie" nemen we het grep + sed commando van een populaire weer-geeklet en leggen het beetje bij beetje uit. Ga je gang en download de sample-geeklet. Open het bestand na downloaden met een teksteditor van welke aard dan ook. U zult merken dat het niet meer is dan een XML-bestand. Als je geen ervaring hebt met XML, wees maar niet bang - Josh deed al een geweldig artikel over Geektool en zijn ins en outs. We zullen het vandaag niet hebben over de alledaagse dingen. Laten we ons in plaats daarvan concentreren op het gedeelte tussen de tags:

 curl - silent "http://xml.weather.yahoo.com/forecastrss?w=28348727&u=c" | grep -E '(huidige voorwaarden: |// '-e's /// '-e's /<\/b>// '-e's /
// '-e' s /// '-e's /<\/description>//'

Deze cryptische puinhoop is een eenvoudig Terminal-commando - niets meer. Je kunt het zelfs in Terminal plakken en je krijgt de weersomstandigheden voor Makati City op de Filippijnen, die de oorspronkelijke auteur heeft ingesteld om te downloaden. De geeklet vertelt Geektool om het commando uit te voeren en om het even welke output te nemen die het krijgt door het uit te voeren. Laten we er eens naar kijken, pijp segment voor buis segment, en in detail uitleggen:

curl - silent "http://xml.weather.yahoo.com/forecastrss?w=28348727&u=c"

Krul is een hulpmiddel voor het overbrengen van gegevens met een URL-syntaxis. Dit betekent dat het naar een URL kan gaan en er gegevens uit kan halen.

Krul is een hulpmiddel dat wordt gebruikt voor het overbrengen van gegevens met een URL-syntaxis op de opdrachtregel

Als u de vermelde URL in uw browser plakt (of gewoon hier klikt), ziet u dat u een XML-bestand van Yahoo! - ze hebben een service voor live weersomstandigheden waar u gemakkelijk toegang tot hebt en waarmee u gegevens kunt ophalen. Dit is exact hetzelfde wat je krijgt als je Krul het; alleen in plaats van de browser wordt de invoer naar Terminal verzonden. De --stil vlag vertelt krullen om stil te zijn over voortgang, status en fouten, zodat de enige uitvoer die we krijgen de uitvoer is die we nodig hebben (of niets, als het mislukt).

grep -E '(huidige voorwaarden: | 

Het pijpeigenschap volgt, wat betekent dat de uitvoer van Krul wordt in grep als invoer verzonden. Grep ontvangt dit gedownloade XML-bestand in tekstformaat en voert een zoekopdracht uit met de -E vlag, wat uitgebreide reguliere expressie betekent. De waarde waarnaar wordt gezocht, is de tekenreeks De huidige omstandigheden: of C (het pijppersonage in een ereg betekent "of"). Voor meer informatie, als u het volgende in ons vorige voorbeeld hebt getypt:

grep -E '(tijger | weh)' jungle.txt

je zou krijgen

Een tijger ontwaakt in het moeras Wimoweh, wimoweh, wimoweh, wimoweh

omdat het alle regels retourneert die "tijger" of "weh" bevatten.

Dus als we deze twee eerste pijpsegmenten als volgt samenvoegen:

curl - silent "http://xml.weather.yahoo.com/forecastrss?w=28348727&u=c" | grep -E '(huidige voorwaarden: | 

we krijgen het volgende:

De huidige omstandigheden:
Haze, 23 C

Maar we willen alleen "Haze, 23 C" krijgen. Dit is waar sed komt binnen. We vervangen eenvoudig alles wat we niet willen met een lege string (niets) en verwijderen die dus effectief.

sed -e's / Huidige voorwaarden: // '-e's /
// '-e's /// '-e's /<\/b>// '-e's /
// '-e' s /// '-e's /<\/description>//'

De -e vlag is kort voor --expressie = en stelt ons in staat om meerdere te ketenen sed commando's. Daarom vervangen we eerst de string "Current Conditions:" door niets, gevolgd door vervanging
met niets, etc. totdat we het mogelijke einde van de regel bereiken ().

Uiteindelijk is alles wat overblijft "Haze, 23 C".

Ik moet vermelden dat de geeklet die we als voorbeeld hebben gebruikt veel beter had kunnen worden gedaan, maar de enorme complexiteit van het gebruikte commando leek een uitstekende gelegenheid om meerdere voorbeelden tegelijkertijd te behandelen. De auteur kan bijvoorbeeld eenvoudig de regel met "Huidige voorwaarden:" hebben opgehaald en de regel erna met de -A 1 vlag combinatie, zonder te vertrouwen op het temperatuursymbool (in dit geval vertrouwen we op Celsius, maar wat als we Fahrenheit wilden hebben? C grep search zou mislukken). Desalniettemin diende het voorbeeld een doel - en dat was om je kennis te laten maken met de wondere wereld van grep en sed.


Meer middelen

Terwijl het aanleren van geavanceerde reguliere expressies en diepere grep, krul en sed-functionaliteit ver buiten de reikwijdte van dit artikel (en deze website) ligt, kijk gerust naar de volgende bronnen als u meer wilt weten.

  • Sed gids
  • Beginnersgids voor grep
  • Praktische voorbeelden van Unix Grep-commando's
  • Grep-documentatie bij IBM
  • Curl-documentatie
  • Normale uitdrukkingen

Conclusie

Je kent nu de basis van grep, sed en zelfs Krul. Hoewel deze crashcursus nog lang niet genoeg was om u een expert te maken, hopen we dat dit in ieder geval voldoende was om u te interesseren om uw eigen gegevensverzameling en -vragen uit te proberen. Op zijn minst is het iets om over te praten rond de waterkoeler op maandag.

Ik hoop dat je het leuk vond, en als je een uitdaging hebt, probeer dan de Geeklet te herschrijven om niet alleen agnostisch temperatuursymbool te zijn, maar ook om de locatie van de gebruiker op zichzelf te achterhalen, zonder dat je de 'w 'parameter in de Yahoo! URL.