Grep-personages voor en na de wedstrijd?

Dit gebruiken:

grep -A1 -B1 "test_pattern" file

zal één regel produceren voor en na het overeenkomende patroon in het bestand. Is er een manier om geen regels maar een gespecificeerd aantal tekens weer te geven?

De regels in mijn bestand zijn behoorlijk groot, dus ik ben niet geïnteresseerd in het afdrukken van de hele regel, maar bekijk de overeenkomst alleen in context. Eventuele suggesties over hoe dit te doen?

92

5 antwoord

3 tekens voor en 4 tekens erachter

$> echo "some123_string_and_another" | grep -o -P '.{0,3}string.{0,4}'
23_string_and
116
toegevoegd
Zoals geïmpliceerd door @Benubird is dit qua prestaties onmogelijk te gebruiken voor enorme bestanden met een gematigd brede omgeving die gewenst is voor het matchdoel.
toegevoegd de auteur matanster, de bron
Een goed antwoord voor kleine hoeveelheden gegevens, maar het begint traag te worden wanneer u meer dan 100 tekens vergelijkt, bijvoorbeeld in mijn gigantische XML-bestand wil ik {1.200} voor en na, en het is te traag om te gebruiken.
toegevoegd de auteur Benubird, de bron
Op OSX installeer via: brew homebrew/dupes/grep en voer het uit als ggrep .
toegevoegd de auteur kenorb, de bron
De awk-versie van @amit_g is veel sneller.
toegevoegd de auteur ssobczak, de bron
Om onverklaarbare redenen, dit drukt voor mij een bepaald aantal regels prachtige uitvoer af, en zegt vervolgens "Aborted", telkens hetzelfde aantal regels, wat afhangt van wat ik zoek, maar nooit het volledige aantal wedstrijden is, door ver. bash 4.1.2 (1) en grep 2.6.3, CentOS 6.5.
toegevoegd de auteur Kev, de bron
De -E-versie hieronder heeft om de een of andere reden dit probleem niet. Als ik ook naar iets zoek dat niet bestaat, krijg ik alleen de regel afgebroken .
toegevoegd de auteur Kev, de bron
Niet beschikbaar op Mac OSX, dus dit is echt geen algemeen beschikbare oplossing. De -E-versie (hieronder weergegeven) is een betere oplossing. Wat is -P? Lees verder ... -P, --perl-regexp Interpreteer PATROON als een reguliere expressie perl (PCRE, zie hieronder). Dit is zeer experimenteel en grep-P kan waarschuwen voor niet-geïmplementeerde functies.
toegevoegd de auteur Xofo, de bron
grep -E -o ".{0,5}test_pattern.{0,5}" test.txt 

Dit komt overeen met maximaal 5 tekens vóór en na uw patroon. De schakeloptie -o geeft grep de opdracht om alleen de overeenkomst weer te geven en -E om een ​​uitgebreide reguliere expressie te gebruiken. Zorg ervoor dat u de aanhalingstekens rond uw uitdrukking plaatst, anders kan het worden geïnterpreteerd door de shell.

79
toegevoegd
Goed antwoord, interessant dat het is afgesloten met 2 ^ 8-1 voor de lengte in de {} dus {0,255} werkt {0,256} geeft grep: ongeldige herhalingsteller (s)
toegevoegd de auteur CodeMonkey, de bron

Je zou kunnen gebruiken

awk '/test_pattern/ {
    match($0, /test_pattern/); print substr($0, RSTART - 10, RLENGTH + 20);
}' file
25
toegevoegd
Kan iemand dit voor meerdere wedstrijden bijwerken?
toegevoegd de auteur Pranab, de bron
hoe kun je dit gebruiken om meerdere overeenkomsten per regel te vinden?
toegevoegd de auteur koox00, de bron
Werkt ook goed met wat grotere bestanden
toegevoegd de auteur Touko, de bron
Wat is de betekenis van het eerste getal in de paren met paren tussen accolades? Zoals de 0's in "grep -E -o". {0,5} testpatroon. {0,5} "test.txt"?
toegevoegd de auteur Lew Rockwell Fan, de bron

Je bedoelt zo:

grep -o '.\{0,20\}test_pattern.\{0,20\}' file

?

Dat zal maximaal twintig tekens aan beide zijden van testpatroon \/code> afdrukken. De notatie \ {0,20 \} is te vergelijken met * , maar geeft nul tot twintig herhalingen op in plaats van nul of meer. De -o zegt om alleen de wedstrijd zelf weer te geven, in plaats van de hele regel.

15
toegevoegd
Deze opdracht werkt niet voor mij: grep: ongeldige inhoud van \ {\}
toegevoegd de auteur Alexander Pravdin, de bron
Deze werkte in de OSX-terminal.
toegevoegd de auteur hapi, de bron

Met gawk kunt u de matchfunctie gebruiken:

    x="hey there how are you"
    echo "$x" |awk --re-interval '{match($0,/(.{4})how(.{4})/,a);print a[1],a[2]}'
    ere   are

Als je het goed vindt met perl , een flexibelere oplossing: volgende zal drie tekens afdrukken vóór het patroon gevolgd door het werkelijke patroon en vervolgens 5 tekens na het patroon.

echo hey there how are you |perl -lne 'print "$1$2$3" if /(.{3})(there)(.{5})/'
ey there how

Dit kan ook op woorden worden toegepast in plaats van alleen op tekens.Volgende zal één woord afdrukken vóór de eigenlijke tekenreeks.

echo hey there how are you |perl -lne 'print $1 if /(\w+) there/'
hey

Hierna zal één woord na het patroon worden afgedrukt:

echo hey there how are you |perl -lne 'print $2 if /(\w+) there (\w+)/'
how

Hierna wordt één woord vóór het patroon afgedrukt, vervolgens het eigenlijke woord en vervolgens één woord na het patroon:

echo hey there how are you |perl -lne 'print "$1$2$3" if /(\w+)( there )(\w+)/'
hey there how
0
toegevoegd