Jak "grepować" określone zakresy linii pliku

Są często chwile, kiedy będę grep-n whatev pliku, aby znaleźć to, czego szukam. Say the output is

1234: whatev 1
5555: whatev 2
6643: whatev 3

Jeśli chcę to po prostu wyodrębnić linie między 1234 i 5555, czy jest jakieś narzędzie do tego? W przypadku plików statycznych mam skrypt, który robi wc-l pliku, a następnie robi matematykę, aby podzielić go z ogonem i głową, ale to nie działa tak dobrze z plikami dziennika, które są stale zapisywane.

Author: Scorchio, 2010-05-26

6 answers

Spróbuj użyć sed, jak wspomniano na http://linuxcommando.blogspot.com/2008/03/using-sed-to-extract-lines-in-text-file.html . na przykład użyj

sed '2,4!d' somefile.txt

Aby wydrukować od drugiej linii do czwartej linii jakiegoś pliku.txt. (I nie zapomnij sprawdzić http://www.grymoire.com/Unix/Sed.html sed jest wspaniałym narzędziem.)

 95
Author: Scorchio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-26 15:17:07

Następujące polecenie wykona to, o co prosiłeś "wyodrębnij linie między 1234 a 5555" w someFile.

sed -n '1234,5555p' someFile

 35
Author: javaPlease42,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-01 13:36:57

Jeśli dobrze rozumiem, chcesz znaleźć wzór między dwoma numerami linii. Awk one-liner może być

awk '/whatev/ && NR >= 1234 && NR <= 5555' file

Nie musisz uruchamiać grep, a następnie sed.

Perl one-liner:

perl -ne 'if (/whatev/ && $. >= 1234 && $. <= 5555') {print}' file
 8
Author: Mark Lakata,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-07 16:48:56

Numery linii są w porządku, jeśli możesz zagwarantować pozycję tego, co chcesz. Przez lata moim ulubionym smakiem tego było coś takiego:

sed "/First Line of Text/,/Last Line of Text/d" filename

, która usuwa wszystkie linie od pierwszej do ostatniej, włącznie z tymi liniami.

Użyj sed -N z "p" zamiast "d", aby wydrukować te linie. O wiele bardziej przydatne dla mnie, ponieważ Zwykle Nie wiem, gdzie są te linie.

 5
Author: psbrightly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-02 19:09:45

Jeśli chcesz linii zamiast zakresów linii, możesz to zrobić za pomocą Perla: np. jeśli chcesz pobrać linię 1, 3 i 5 z pliku, powiedz /etc/passwd:

perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd
 0
Author: dagelf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-23 15:23:59

Umieść to w pliku i spraw, aby było wykonywalne:

#!/bin/bash
start=`grep -n $1 < $3 | head -n1 | cut -d: -f1; exit ${PIPESTATUS[0]}`
if [ ${PIPESTATUS[0]} -ne 0 ]; then
    echo "couldn't find start pattern!" 1>&2
    exit 1
fi
stop=`tail -n +$start < $3 | grep -n $2 | head -n1 | cut -d: -f1; exit ${PIPESTATUS[1]}`
if [ ${PIPESTATUS[0]} -ne 0 ]; then
    echo "couldn't find end pattern!" 1>&2
    exit 1
fi

stop=$(( $stop + $start - 1))

sed "$start,$stop!d" < $3

Uruchom plik z argumentami (zauważ, że skrypt nie obsługuje spacji w argumentach!):

  1. Starting grep pattern
  2. zatrzymanie wzorca grepa
  3. ścieżka do pliku

Aby użyć Twojego przykładu, użyj argumentów: 1234 5555 myfile.txt

Zawiera linie ze wzorem startu i zatrzymania.

 0
Author: Janus Troelsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-08 13:00:08