Níže je uveden text v souboru:

Pseudo name=Apple Code=42B state=fault Pseudo name=Prance Code=43B state=good 

Musím pozdravit „42B“ a získat výstup z výše uvedeného textu jako:

Pseudo name=Apple Code=42B state=fault 

Má někdo představu, jak toho dosáhnout pomocí grep / awk / sed?

Komentáře

  • Tuto otázku jste označili pouze " grep ". Hledáte tedy pouze " grep " řešení? V otázce zadáte také awk & sed. Můžeme přidat tyto značky? Když jsem včera upravoval otázku, nebyl jsem si ' jistý svým záměrem.
  • stackoverflow.com/ questions / 12024410 / …

odpověď

S awk

awk -v RS="" "/42B/" file 

RS= změní oddělovač vstupních záznamů z nového řádku na prázdné řádky. Pokud kterékoli pole v záznamu obsahuje /42B/ vytiskněte záznam.

"" (prázdný řetězec) je kouzlo hodnota použitá k vyjádření prázdných řádků podle POSIX :

If RS je null, pak jsou záznamy odděleny sekvencemi skládajícími se z <newline> plus jednoho nebo více prázdných řádky, úvodní nebo koncové prázdné řádky nesmí vést k prázdným záznamům na začátku nebo na konci vstupu a <newline> musí být vždy oddělovač pole, bez ohledu na hodnotu FS je.

Výstupní odstavce nebudou být odděleny, protože oddělovač výstupu zůstává jediným novým řádkem. Abyste zajistili, že mezi výstupními odstavci bude prázdný řádek, nastavte oddělovač výstupních záznamů na dva nové řádky:

awk -v RS="" -v ORS="\n\n" "/42B/" file 

Komentáře

  • +1 pro elegantní řešení. Soubor však ' nemusíte přesměrovat …
  • prsty byly na autopilotu.
  • @jasonwryan, pokud nepotřebujete přístup na název souboru v rámci awk (FILENAME), ' není špatný nápad použít přesměrování, aby se předešlo problémům s názvem souboru obsahujícím = nebo počínaje - (nebo -) zajišťuje konzistentní chybové zprávy a vyhne se spuštění awk nebo jiným přesměrováním, pokud nelze vstupní soubor ' otevřít.

Odpověď

Předpokládejme, že data jsou strukturována tak, aby vždy byly řádky před a po, které chcete. = „d01d1d6240″>

(po) a -B (dříve) přepne a řekne mu, aby zahrnoval 1 řádek před zápasem a 1 řádek po něm:

$ grep -A 1 -B 1 "42B" sample.txt Pseudo name=Apple Code=42B state=fault 

Pokud chcete stejný počet řádků před a za hledaným výrazem můžete použít -C (kontextový) přepínač:

$ grep -C 1 "42B" sample.txt Pseudo name=Apple Code=42B state=fault 

Pokud chcete být přísnější při porovnávání více řádků, můžete použít nástroj pcregrep a vzor na více řádcích:

$ pcregrep -M "Pseudo.*\n.*42B.*\nstate.*" sample.txt Pseudo name=Apple Code=42B state=fault 

Výše uvedený vzor odpovídá následovně:

  • -M – více řádků
  • "Pseudo.*\n.*42B.*\nstate.*" – odpovídá skupině řetězců, kde první řetězec začíná slovem "Pseudo" následovány libovolnými znaky až do konce řádku \n, následovanými libovolnými znaky až do řetězce "42B" následovanými libovolnými znaky až do další konec řádku (\n), za kterým následuje řetězec "state" následovaný libovolnými znaky.

Komentáře

  • (kontext) lze použít jako zkratku, pokud -A a -B jsou stejné.
  • @DavidBaggerman – děkuji. Přidal to do odpovědi.
  • Proč ten, kdo hlasoval? To odpovídá na otázku.

Odpověď

grep z některé příchutě Unixu mají pro „odstavec“ příznak -p. Vím, že AIX ano .

grep -p 42B <myfile> 

by tam udělal přesně to, o co tam žádáte . YMMV a GNU grep tento příznak nemají.

Komentáře

  • Příznak -p by bylo skvělé. Zvláště pokud se používá společně s -v, takže můžete z výstupu vyloučit celé odstavce.

Odpověď

Existuje pravděpodobně podobně snadný způsob, jak to udělat pomocí awk, ale v perlu:

cat file | perl -ne "BEGIN { $/="\n\n" }; print if $_ =~ /42B/;" 

To v zásadě znamená rozdělit soubor na bloky oddělené prázdnými řádky a potom vytisknout pouze bloky, které odpovídají vašemu regulárnímu výrazu.

Komentáře

odpověď

Další perlové řešení bez koncový prázdný řádek:

perl -00ne "if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}" foo 

Example

% perl -00ne "if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}" foo Pseudo name=Apple Code=42B state=fault % cat foo Pseudo name=Apple Code=42B state=fault Pseudo name=Prance Code=43B state=good 

Komentáře

  • Nebo kratší (a tedy čitelnější), jak napsal triplee v komentáři: perl -00 -ne 'print if /42B/' file.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *