代码之家  ›  专栏  ›  技术社区  ›  TiGz

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

  •  1
  • TiGz  · 技术社区  · 16 年前

    在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 回复  |  直到 16 年前
        1
  •  0
  •   SiegeX    16 年前

    下面的脚本将执行您要求的所有操作, 包括奖金 .将此脚本放在顶层目录中,该目录包含所有可能具有要裁剪的“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
  •  2
  •   Zeograd    16 年前

    我提议这样做:

    # 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,只显示那些(包括在内的)。 它可以被优化(只增加一次),但它应该是有效的。

        3
  •  0
  •   Adam Luchjenbroers    16 年前

    我可能会用猫和 awk . 类似的东西

    cat *.log | awk 'BEGIN { sidFound = 0; } {
        if (*check for SID here*) {
             sidFound = !sidFound;
        }
    
        if (sidFound) {
             print $0
        }
     }'
    
        4
  •  0
  •   Richard Gaywood    16 年前

    或者几行Perl,或者:

    grep -no <session_ID> <log_file>
    

    (在会话ID为on的情况下记录第一个和最后一个行号)

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

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

    我现在想不出一个办法让它成为一条直线。

        5
  •  0
  •   ghostdog74    16 年前
    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
    
        6
  •  0
  •   Fritz G. Mehner    16 年前

    以下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
    
        7
  •  0
  •   ADEpt    16 年前

    如何:

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

    ?