GNU/Linux >> Znalost Linux >  >> Linux

10 praktických příkladů příkazů Grep pro vývojáře

Nedávno jsem začal spolupracovat s Asciidoctor.js a on projekt Asciidoctor.js-pug a Asciidoctor-templates.js.

Není vždy snadné být okamžitě efektivní, když se poprvé ponoříte do kódové báze obsahující několik tisíc řádků. Ale mou tajnou zbraní, jak najít cestu přes tolik řádků kódu, je grep nástroj.

Podělím se s vámi o použití příkazu grep v Linuxu s příklady.

Reálné užitečné příklady příkazů grep v Linuxu

Pokud se podíváte do man , uvidíte krátký popis grep nástroj:„tisknout čáry odpovídající vzoru.“

Nenechte se však zmást takovou skromnou definicí:grep je jedním z nejužitečnějších nástrojů v unixové sadě nástrojů a existuje nespočet příležitostí k jeho použití, jakmile pracujete s textovými soubory.

Vždy je lepší mít příklady z reálného světa, abyste se naučili, jak věci fungují. Použiji tedy zdrojový strom Asciidoctor.js k ilustraci některých grep schopnosti.

Tento zdrojový strom si můžete stáhnout z GitHubu, a pokud chcete, můžete se dokonce podívat na stejnou sadu změn, kterou jsem použil při psaní tohoto článku. To zajistí, že získáte výsledky naprosto identické s těmi, které jsou popsány ve zbytku tohoto článku:

git clone https://github.com/asciidoctor/asciidoctor.js
cd asciidoctor.js
git checkout v1.5.6-rc.1

1. Najít všechny výskyty řetězce (základní použití)

Asciidoctor.js podporuje Nashorn JavaScript engine pro platformu Java. Neznám Nashorn, takže bych mohl využít této příležitosti a dozvědět se o něm více prozkoumáním částí projektu odkazujících na tento JavaScript engine.

Jako výchozí bod jsem zkontroloval, zda v package.json nejsou nějaká nastavení související s Nashornem soubor popisující závislosti projektu:

[email protected]:~$ grep nashorn package.json
    "test": "node npm/test/builder.js && node npm/test/unsupported-features.js && node npm/test/jasmine-browser.js && node npm/test/jasmine-browser-min.js && node npm/test/jasmine-node.js && node npm/test/jasmine-webpack.js && npm run test:karmaBrowserify && npm run test:karmaRequirejs && node npm/test/nashorn.js",

Ano, zjevně tam byly nějaké testy specifické pro Nashorn. Pojďme to tedy prozkoumat trochu více.

2. Vyhledávání v sadě souborů bez rozlišení malých a velkých písmen

Nyní se chci blíže podívat na soubory z ./npm/test/ adresář výslovně zmiňuje Nashorn.

Vyhledávání bez ohledu na velikost písmen (-i option) je zde pravděpodobně lepší, protože potřebuji najít oba odkazy na nashorn a Nashorn (nebo jakákoli jiná kombinace velkých a malých písmen):

[email protected]:~$ grep -i nashorn npm/test/*.js
npm/test/nashorn.js:const nashornModule = require('../module/nashorn');
npm/test/nashorn.js:log.task('Nashorn');
npm/test/nashorn.js:nashornModule.nashornRun('jdk1.8.0');

Zde byla skutečně užitečná necitlivost na malá a velká písmena. Jinak bych vynechal require('../module/nashorn') prohlášení. Nepochybně bych měl ten soubor prozkoumat podrobněji později.

3. Najděte všechny neodpovídající soubory

Mimochodem, jsou v npm/test/ nějaké soubory, které nejsou specifické pro Nashorm adresář? K zodpovězení této otázky můžeme použít možnost „tisknout neodpovídající soubory“ grep (-L možnost):

sh$ grep -iL nashorn npm/test/*
npm/test/builder.js
npm/test/jasmine-browser-min.js
npm/test/jasmine-browser.js
npm/test/jasmine-node.js
npm/test/jasmine-webpack.js
npm/test/unsupported-features.js

Všimněte si, jak pomocí -L zvolte výstup grep se změnil tak, aby zobrazoval pouze názvy souborů. Žádný z výše uvedených souborů tedy neobsahuje řetězec „nashorn“ (bez ohledu na velikost písmen). To neznamená, že s touto technologií nějak nesouvisí, ale alespoň tam nejsou písmena „n-a-s-h-o-r-n“.

4. Hledání vzorů do skrytých souborů a rekurzivně do podadresářů

Poslední dva příkazy používaly vzor shell glob k předání seznamu souborů k prozkoumání do grep příkaz.

Má to však určitá inherentní omezení:hvězdička (* ) nebude odpovídat skrytým souborům. Ani to nebude odpovídat souborům (nakonec) obsaženým v podadresářích.

Řešením by bylo zkombinovat grep pomocí příkazu find namísto spoléhání se na vzor shell glob:

# This is not efficient as it will spawn a new grep process for each file
[email protected]:~$ find npm/test/ -type f -exec grep -iL nashorn \{} \;
# This may have issues with filenames containing space-like characters
[email protected]:~$ grep -iL nashorn $(find npm/test/ -type f)

Jak jsem to zmínil v komentářích k bloku kódu výše, každé z těchto řešení má nevýhody.

Pokud jde o názvy souborů obsahující znaky podobné mezerám, nechám vás prozkoumat grep -z možnost, která v kombinaci s -print0 možnost find příkaz, může tento problém zmírnit. Neváhejte a použijte sekci komentářů na konci tohoto článku a podělte se o své nápady na toto téma!

Nicméně lepším řešením by bylo použití „rekurzivního“ (-r ) možnost grep . S touto volbou zadáte na příkazovém řádku kořen vašeho vyhledávacího stromu (počáteční adresář) namísto explicitního seznamu jmen souborů k prozkoumání.

Pomocí -r grep prohledá všechny soubory v zadaném adresáři, včetně skrytých, a poté rekurzivně sestoupí do libovolného podadresáře:

[email protected]:~$ grep -irL nashorn npm/test/npm/
npm/test/builder.js
npm/test/jasmine-browser-min.js
npm/test/jasmine-browser.js
npm/test/jasmine-node.js
npm/test/jasmine-webpack.js
npm/test/unsupported-features.js

Vlastně s touto možností bych také mohl začít svůj průzkum o úroveň výše, abych viděl, že existují testy bez NPM, které cílí i na Nashorn:

[email protected]:~$ grep -irL nashorn npm/

Nechal jsem vás otestovat tento příkaz sami, abyste viděli jeho výsledek; ale jako nápovědu mohu říci, že byste měli najít mnohem více odpovídajících souborů!

5. Filtrování souborů podle jejich názvu (pomocí regulárních výrazů)

Zdá se tedy, že v tomto projektu jsou nějaké testy specifické pro Nashorn. Vzhledem k tomu, že Nashorn je Java, další otázka, která by mohla být vznesena, by byla „existují v projektu nějaké zdrojové soubory Java, které výslovně zmiňují Nashorn?“ .

V závislosti na verzi grep pro odpověď na tuto otázku existují alespoň dvě řešení.

První z nich je použití grep k nalezení všech souborů obsahujících vzor „nashorn“, pak výstup tohoto prvního příkazu přesměrujte do druhého grep instance filtrující zdrojové soubory jiné než Java:

[email protected]:~$ grep -ir nashorn ./ | grep "^[^:]*\.java"
./spec/nashorn/AsciidoctorConvertWithNashorn.java:public class AsciidoctorConvertWithNashorn {
./spec/nashorn/AsciidoctorConvertWithNashorn.java:    ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/AsciidoctorConvertWithNashorn.java:    engine.eval(new FileReader("./spec/nashorn/asciidoctor-convert.js"));
./spec/nashorn/BasicJavascriptWithNashorn.java:public class BasicJavascriptWithNashorn {
./spec/nashorn/BasicJavascriptWithNashorn.java:    ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/BasicJavascriptWithNashorn.java:    engine.eval(new FileReader("./spec/nashorn/basic.js"));

První polovina příkazu by již měla být srozumitelná. Ale co ta část „^[\^:]*\\.java“?

Pokud nezadáte -F možnost, grep předpokládá, že vyhledávací vzor je regulární výraz. To znamená, že kromě jednoduchých znaků, které budou odpovídat doslovně, máte přístup k sadě metaznaků pro popis složitějších vzorů. Vzor, který jsem použil výše, bude odpovídat pouze:

  • ^ začátek řádku
  • [^:]* následuje sekvence libovolných znaků kromě dvojtečky
  • \. následuje tečka (tečka má v regulárním výrazu zvláštní význam , takže jsem to musel chránit zpětným lomítkem, abych vyjádřil, že chci doslovnou shodu)
  • java a následují čtyři písmena „java.“

V praxi od grep použije dvojtečku k oddělení názvu souboru od kontextu, ponechám pouze řádky s .java v sekci název souboru. Stojí za zmínku by odpovídat také .javascript názvy souborů. To je něco, co jsem nechal zkusit vyřešit sám, pokud chcete.

6. Filtrování souborů podle jejich názvu pomocí grep

Regulární výrazy jsou extrémně silné. V tomto konkrétním případě se to však zdá být přehnané. Nemluvě o výše uvedeném řešení, trávíme čas zkoumáním všech souborů při hledání vzoru „nashorn“ – většina výsledků je zahozena ve druhém kroku potrubí.

Pokud používáte GNU verzi grep , což je pravděpodobné, pokud používáte Linux, ale máte jiné řešení s --include volba. To dává pokyn grep pro vyhledávání pouze v souborech, jejichž název odpovídá danému vzoru glob:

[email protected]:~$ grep -ir nashorn ./ --include='*.java'
./spec/nashorn/AsciidoctorConvertWithNashorn.java:public class AsciidoctorConvertWithNashorn {
./spec/nashorn/AsciidoctorConvertWithNashorn.java:    ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/AsciidoctorConvertWithNashorn.java:    engine.eval(new FileReader("./spec/nashorn/asciidoctor-convert.js"));
./spec/nashorn/BasicJavascriptWithNashorn.java:public class BasicJavascriptWithNashorn {
./spec/nashorn/BasicJavascriptWithNashorn.java:    ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/BasicJavascriptWithNashorn.java:    engine.eval(new FileReader("./spec/nashorn/basic.js"));

7. Hledání slov

Zajímavostí projektu Asciidoctor.js je, že jde o vícejazyčný projekt. Ve svém jádru je Asciidoctor napsán v Ruby, takže aby byl použitelný ve světě JavaScriptu, musí být „transpilován“ pomocí Opal, překladače mezi zdroji z Ruby do JavaScriptu. Další technologie, o které jsem předtím nevěděl.

Po prozkoumání specifik Nashornu jsem si tedy zadal úkol lépe porozumět Opal API. Jako první krok v tomto questu jsem prohledal všechny zmínky o Opal globální objekt v souborech JavaScript projektu. Může se objevit v afektech (Opal = ), členský přístup (Opal. ) nebo možná i v jiných kontextech. Regulární výraz by stačil. Ještě jednou však grep má nějaké lehčí řešení k vyřešení tohoto běžného případu použití. Pomocí -w možnost, bude odpovídat pouze slovům , tedy vzory, kterým předchází a za nimi následuje neslovní znak. Neslovný znak je buď začátek řádku, konec řádku nebo jakýkoli znak, který není ani písmenem, ani číslicí, ani podtržítkem:

[email protected]:~$ grep -irw --include='*.js' Opal .
...

8. obarvení výstupu

Nekopíroval jsem výstup předchozího příkazu, protože existuje mnoho shod. Když je výstup takto hustý, možná budete chtít přidat trochu barvy pro usnadnění porozumění. Pokud to ještě není ve vašem systému nakonfigurováno ve výchozím nastavení, můžete tuto funkci aktivovat pomocí GNU --color možnost:

[email protected]:~$ grep -irw --color=auto --include='*.js' Opal .
...

Měli byste získat stejně dlouhý výsledek jako dříve, ale tentokrát by se hledaný řetězec měl zobrazit barevně, pokud tomu tak již nebylo.

9. Počítání odpovídajících řádků nebo odpovídajících souborů

Dvakrát jsem zmínil, že výstup předchozích příkazů byl velmi dlouhý. Jak dlouho přesně?

[email protected]:~$ grep -irw --include='*.js' Opal . | wc -l
86

To znamená, že máme celkem 86 odpovídajících řádků ve všech zkoumané soubory. Kolik různých souborů se však shoduje? Pomocí -l možnost můžete omezit grep výstup odpovídajících souborů místo zobrazení odpovídajících řádků . Takže tato jednoduchá změna řekne, kolik souborů se shoduje:

[email protected]:~$ grep -irwl --include='*.js' Opal . | wc -l
20

Pokud vám to připomíná -L možnost, žádné překvapení:jak je poměrně běžné, k rozlišení doplňkových možností se používají malá/velká písmena. -l zobrazí odpovídající názvy souborů. -L zobrazí neodpovídající názvy souborů. Jako další příklad vám dovolím zkontrolovat manuál pro -h /-H možnosti.

Uzavřeme tuto závorku a vraťme se k našim výsledkům:86 odpovídajících řádků. 20 odpovídajících souborů. Jak jsou však distribuovány odpovídající řádky v odpovídajících souborech ? Můžeme to vědět pomocí -c možnost grep to bude počítat počet odpovídajících řádků na zkoumaný soubor (včetně souborů s nulovou shodou):

[email protected]:~$ grep -irwc --include='*.js' Opal .
...

Tento výstup často potřebuje nějaké následné zpracování, protože zobrazuje své výsledky v pořadí, v jakém byly soubory prozkoumány, a také obsahuje soubory bez jakékoli shody – něco, co nás obvykle nezajímá. To poslední je docela snadné vyřešit:

[email protected]:~$ grep -irwc --include='*.js' Opal . | grep -v ':0$'

Co se týče řazení věcí, můžete přidat příkaz sort na konec kanálu:

[email protected]:~$ grep -irwc --include='*.js' Opal . | grep -v ':0$' | sort -t: -k2n

Nechal jsem vás zkontrolovat sort příkazový manuál pro přesný význam možností, které jsem použil. Nezapomeňte se podělit o své poznatky pomocí sekce komentářů níže!

10. Nalezení rozdílu mezi dvěma odpovídajícími množinami

Pokud si vzpomínáte, před několika příkazy jsem hledal slovo "Opál." Pokud však hledám ve stejné sadě souborů všechny výskyty řetězce "Opál," dostávám dalších asi dvacet odpovědí:

[email protected]:~$ grep -irw --include='*.js' Opal . | wc -l
86
[email protected]:~$ grep -ir --include='*.js' Opal . | wc -l
105

Bylo by zajímavé najít rozdíl mezi těmito dvěma sadami. Jaké jsou tedy řádky obsahující čtyři písmena „opál“ v řadě, ale kde tato čtyři písmena netvoří celé slovo?

Na tuto otázku není tak snadné odpovědět. Protože stejné řádek může obsahovat obě slovo Opal stejně jako nějaké větší slovo obsahující tato čtyři písmena. Ale jako první přiblížení můžete použít tento kanál:

[email protected]:~$ grep -ir --include='*.js' Opal . | grep -ivw Opal
./npm/examples.js:  const opalBuilder = OpalBuilder.create();
./npm/examples.js:  opalBuilder.appendPaths('build/asciidoctor/lib');
./npm/examples.js:  opalBuilder.appendPaths('lib');
...

Moje další zastávka by zřejmě byla prozkoumat opalBuilder objekt, ale to bude na jiný den.

Poslední slovo

Samozřejmě nepochopíte organizaci projektu, tím méně architekturu kódu, když vydáte pár grep příkazy!

Považuji však tento příkaz za nevyhnutelný pro identifikaci referenčních hodnot a výchozích bodů při zkoumání nové kódové základny.

Doufám tedy, že vám tento článek pomohl pochopit sílu grep příkaz a že si jej přidáte do truhly s nástroji. Bezpochyby toho nebudete litovat!


Linux
  1. 8 Praktické příklady příkazu Linux Xargs pro začátečníky

  2. Příklady příkazů DNF pro začátečníky

  3. 10 Praktické příklady použití příkazu scp

  1. cp Command v Linuxu:7 praktických příkladů

  2. Linux Shutdown Command:5 praktických příkladů

  3. Příkaz nslookup:7 praktických příkladů

  1. 14 Příklady příkazů Grep v Linuxu

  2. 12 Příklady IP příkazů pro uživatele Linuxu

  3. 16 Praktické příklady příkazu Linux LS pro začátečníky