Grep, zaczynając od stałego tekstu, aż do pierwszej pustej linii

9

Mam taki plik prova.txt:

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4

extra1
extra2
bla

Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561

extra2
bla
bla

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131

i muszę przejść z „Zacznij chwytać tutaj” do pierwszej pustej linii. Dane wyjściowe powinny wyglądać następująco:

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4

Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561

Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131

Jak widać, wiersze po „Zacznij chwytać tutaj” są losowe, więc flaga -A -B grep nie działa:

cat prova.txt | grep "Start to grab from here" -A 15 | grep -B 15 "^$" > output.txt

Czy możesz mi pomóc znaleźć sposób na złapanie pierwszej linii, która zostanie złapana (jako „Zacznij chwytać stąd”), aż do pustej linii. Nie mogę przewidzieć, ile losowych linii będę mieć po „Zacznij chwytać stąd”.

Każde rozwiązanie kompatybilne z Uniksem jest mile widziane (grep, sed, awk jest lepsze niż Perl lub podobny).

ZMIENIONO: po genialnej odpowiedzi @ john1024 chciałbym wiedzieć, czy można:

1 ° posortuj blok (według Start, aby pobrać stąd: 1, a następnie 1, a następnie 2)

2 ° usuń 4 (losowo alfabetycznie) linie fix1, fix2, fix3, fix4, ale zawsze są 4

3 ° ostatecznie usuwa losowe duplikaty, takie jak polecenie sort -u

Ostateczne wyjście powinno wyglądać następująco:

# fix lines removed - match 1 first time
Start to grab from here: 1
random1
random2
random3
random4

#fix lines removed - match 1 second time
Start to grab from here: 1
#random1 removed cause is a dupe
random22131

#fix lines removed - match 2 that comes after 1
Start to grab from here: 2
random1546
random2561

lub

# fix lines removed - match 1 first time and the second too
Start to grab from here: 1
random1
random2
random3
random4
#random1 removed cause is a dupe
random22131

#fix lines removed - match 2 that comes after 1
Start to grab from here: 2
random1546
random2561

Drugie wyjście jest lepsze niż pierwsze. Potrzebna jest inna magia poleceń unixa.

heisen
źródło
1
Jest to bardzo przydatne do pobierania śladu stosu dla konkretnego wątku z wyjścia Jstack Javy. Cieszę się, że znalazłem to pytanie i odpowiedź!
BenjaminBallard

Odpowiedzi:

13

Korzystanie z awk

Próbować:

$ awk '/Start to grab/,/^$/' prova.txt
Start to grab from here: 1
random1
random2
random3
random4

Start to grab from here: 2
random1546
random2561

Start to grab from here: 3
random45
random22131

/Start to grab/,/^$/określa zakres. Zaczyna się od dowolnej pasującej linii, Start to graba kończy pierwszą pustą linią ^$.

Korzystanie z sed

Z bardzo podobną logiką:

$ sed -n '/Start to grab/,/^$/p' prova.txt
Start to grab from here: 1
random1
random2
random3
random4

Start to grab from here: 2
random1546
random2561

Start to grab from here: 3
random45
random22131

-nmówi sed, aby niczego nie drukował, chyba że wyraźnie o to poprosimy. /Start to grab/,/^$/pkaże mu wydrukować dowolne linie w zakresie zdefiniowanym przez /Start to grab/,/^$/.

John1024
źródło
Twoje rozwiązanie jest idealne, zredagowałem moje zapytanie o dodanie czegoś. Doceń swoją pomoc. Dziękuję
heisen
1

Zamieszczam alternatywne rozwiązanie, ponieważ może być przydatne w niektórych przypadkach użycia. To rozwiązanie nie spełnia dokładnie podanych wymagań, najlepsze rozwiązanie znajdziesz w odpowiedzi na @ John1024.

Możesz użyć awk z ustawionym separatorem rekordów na pusty ciąg, awk zinterpretuje je jako puste znaki nowej linii:

$ awk '/Start/' RS= prova.txt 
Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random2
random3
random4
Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561
Start to grab from here: 1
fix1
fix2
fix3
fix4
random1
random22131

Ta wersja nie zachowuje pustych znaków nowej linii na wyjściu. Pokaże także kontekst przed meczem, jeśli jest obecny. To zachowanie może być bardzo przydatne, gdy szuka się czegoś w pliku, a chcesz zobaczyć blok rozdzielany znakiem nowej linii, którego jest częścią, na przykład:

$ awk '/random1546/' RS= prova.txt 
Start to grab from here: 2
fix1
fix2
fix3
fix4
random1546
random2561

Na przykład uważam to za przydatne, gdy szukam rzeczy w iniplikach.

htaccess
źródło