Как обрезать очень большой текстовый файл между первым и последним вхождением строки? (Linux) - PullRequest
1 голос
/ 16 декабря 2009

В системе Linux у меня очень большой текстовый файл, и мне нужно создать новый текстовый файл, который содержит каждую строку между первым и последним вхождением определенного sessionId (включая эти строки).

Думаю, мне, вероятно, нужно использовать sed или что-то еще?

В качестве бонуса иногда я не знаю, какой файл журнала будет содержать трассировку сеанса. Так что сценарий, который может работать с регулярными выражениями, был бы идеальным. В этом случае я ожидаю, что скрипт найдет первый файл с идентификатором sessionId, а затем обрежет этот файл перед выходом.

Пример файла журнала, который ищет sessionId 1111-ABCD-1111-SOME-GUID:

line one containing other session id: 2222-ABCD-1111-SOME-GUID blaa blaa blaa
line two blaa blaa blaa
line three containing my session id: 1111-ABCD-1111-SOME-GUID blaa blaa blaa
line four containing other session id: 2222-ABCD-1111-SOME-GUID
line five blaa blaa blaa
line six containing other session id: 3333-ABCD-1111-SOME-GUID blaa blaa blaa
line seven containing other session id: 2222-ABCD-1111-SOME-GUID
line eight containing my session id: 1111-ABCD-1111-SOME-GUID blaa blaa blaa
line nine containing other session id: 3333-ABCD-1111-SOME-GUID
line ten containing my session id: 1111-ABCD-1111-SOME-GUID
line eleven
line twelve containing other session id: 3333-ABCD-1111-SOME-GUID blaa blaa blaa
line thirteen containing my session id: 1111-ABCD-1111-SOME-GUID
line fouteen blaa blaa blaa
line fifteen containing other session id: 3333-ABCD-1111-SOME-GUID blaa blaa blaa

выходной файл будет содержать строки три-тринадцать включительно.

Ответы [ 7 ]

2 голосов
/ 16 декабря 2009

Я бы предложил что-то вроде этого:

# Find all occurence of session id in the input file
grep -n "<session id>" "<input file>" > /tmp/grep.$$

# get the first line number of session id appearance
FIRST_LINE=$(head -1 /tmp/grep.$$ | cut -d: -f1)

# get the last line number of session id appearance
LAST_LINE=$(tail -1 /tmp/grep.$$| cut -d: -f1)

# Display only the part (inclusive) in between the first and last session id
sed -n "${FIRST_LINE},${LAST_LINE}p" "<input file>"

Таким образом, вы извлекаете номер строки первого и последнего вхождения вашего шаблона во входном файле, а затем, используя sed, отображаете только те (включены). Его можно оптимизировать (только один раз), но он должен работать.

0 голосов
/ 06 января 2010

А как же:

sed -n "/$session_id/,/$session_id/p" file.txt

0 голосов
/ 16 декабря 2009

Следующий скрипт Perl (session_id.pl) выполняет эту работу:

#!/usr/bin/perl 

my  $session_id = '1111-ABCD-1111-SOME-GUID';

while ( <> ) {
    if ( /$session_id/ ... /$session_id/ ) {
        print;
    }
}

Сделайте его исполняемым и запустите:

./session_id.pl < session.data
0 голосов
/ 16 декабря 2009
gawk 'BEGIN{c=0}
/1111-ABCD-1111-SOME-GUID/{
    f=1
    for(i=1;i<=c;i++) print _[i]
    print
    delete _
    c=0
}
!/1111-ABCD-1111-SOME-GUID/&&f{ _[++c]=$0}
' file
0 голосов
/ 16 декабря 2009

Либо несколько строк Perl, либо:

grep -no <session_ID> <log_file>

(запишите номера первой и последней строки при включенном идентификаторе сеанса)

awk 'NR==3,NR==935' <log_file>

(где 3 и 935 - номера первой и последней строки, возвращаемые командой grep)

В настоящее время я не могу придумать, как сделать это однострочным.

0 голосов
/ 16 декабря 2009

Я бы, наверное, сделал это, используя cat и awk . Что-то вроде

cat *.log | awk 'BEGIN { sidFound = 0; } {
    if (*check for SID here*) {
         sidFound = !sidFound;
    }

    if (sidFound) {
         print $0
    }
 }'
0 голосов
/ 16 декабря 2009

Следующий скрипт выполнит все, что вы просили, , включая бонус . Поместите этот скрипт в каталог верхнего уровня, который содержит все возможные файлы с «uid», который вы хотите обрезать. Сценарий будет рекурсивно искать этот каталог и обрезать все файлы, которые соответствуют, и помещать результат в новый файл с расширением .crp в конце (см. Пример ниже). Я особенно внимательно следил за тем, чтобы этот сценарий работал с любым именем файла, которое вы выбрасываете, будь то пробелы или переводы строк или что-либо в его имени.

#!/bin/bash
uid="1111-ABCD-1111-SOME-GUID"

while IFS= read -r -d $'\0' file; do
    printf "%s\n" "?$uid?+1,\$d" "1,/$uid/-1d" "%p" | ex -s "$file" > "$file".crp
    echo "$file being cropped"
done < <(grep -lZR --exclude="${0#*/}" --exclude="*.crp" "$uid" .)

Результат

$ ./uid.sh
./sample1.txt being cropped
./subdir/sample2.txt being cropped

$ cat ./sample1.txt.crp
line three containing my session id: 1111-ABCD-1111-SOME-GUID blaa blaa blaa
line four containing other session id: 2222-ABCD-1111-SOME-GUID
line five blaa blaa blaa
line six containing other session id: 3333-ABCD-1111-SOME-GUID blaa blaa blaa
line seven containing other session id: 2222-ABCD-1111-SOME-GUID
line eight containing my session id: 1111-ABCD-1111-SOME-GUID blaa blaa blaa
line nine containing other session id: 3333-ABCD-1111-SOME-GUID
line ten containing my session id: 1111-ABCD-1111-SOME-GUID
line eleven
line twelve containing other session id: 3333-ABCD-1111-SOME-GUID blaa blaa blaa
line thirteen containing my session id: 1111-ABCD-1111-SOME-GUID

$ cat ./subdir/sample2.txt.crp
line three containing my session id: 1111-ABCD-1111-SOME-GUID blaa blaa blaa
foo
bar
line eight containing my session id: 1111-ABCD-1111-SOME-GUID blaa blaa blaa
baz
line ten containing my session id: 1111-ABCD-1111-SOME-GUID

Как вы можете видеть в приведенном выше примере, мой скрипт обнаружил два совпадающих файла, один из которых находился в подкаталоге под каталогом верхнего уровня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...