如何在字符串的第一次和最后一次出现之间裁剪一个非常大的文本文件? (Linux)的

时间:2009-12-16 10:10:09

标签: linux shell

在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

输出文件将包含第3行到第13行(包括第3行)。

7 个答案:

答案 0 :(得分:2)

我建议这样的事情:

# 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,只显示那些(包括在内)。 它可以被优化(只打一次),但它应该工作。

答案 1 :(得分:0)

以下脚本将执行您提出的所有内容 ,包括奖励 。将此脚本放在顶级目录中,该目录包含要裁剪的“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

正如您在上面的示例中所看到的,我的脚本找到了两个匹配的文件,其中一个文件位于顶级目录下的子目录中。

答案 2 :(得分:0)

我可能会使用cat和awk这样做。像

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

    if (sidFound) {
         print $0
    }
 }'

答案 3 :(得分:0)

Perl的几行,或者:

grep -no <session_ID> <log_file>

(记下会话ID的第一行和最后一行号码)

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

(其中3和935是grep命令返回的第一个和最后一个行号)

我现在无法想到一种方法来制作一个单行。

答案 4 :(得分:0)

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

答案 5 :(得分:0)

以下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

答案 6 :(得分:0)

怎么样:

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