【问题标题】:chomping file down砍掉文件
【发布时间】:2011-11-25 15:59:48
【问题描述】:

我有一个很大的日志文件,超过 100 万行。 我需要使用正则表达式来找到一个模式,然后开始大吃一惊,直到我遇到另一个正则表达式。所以我最终会得到大约 1500 行。

我知道 sed 允许使用正则表达式,但它可以拆分文件吗?我没有使用 awk 的经验,但我认为这应该可以让我做我需要的事情。不过,我对阅读手册页感到困惑......我会提供一些示例或更简单的解决方案。

【问题讨论】:

  • 您能否提供一些您希望匹配的示例日志文件行和正则表达式?当有一些具体的输入和输出要讨论时,制定解决方案总是更容易。

标签: regex linux sed awk


【解决方案1】:

在 AWK 和 SED 中,您都可以像这样定义 RegEx -

AWK:在 AWK 中,您会注意到我们没有在任何地方写 print。在 AWK 中(基于模式/动作语句,只要模式语句为真,打印就是默认动作。因此在以下情况下,只要 RegEx 模式为真,AWK 就会为我们打印它。

awk '/regex1/,/regex2/' INPUT_FILE > NEW_FILE

SED:在 SED 中,我们使用 -n 选项来禁止打印所有内容的默认行为,并使用带有 p 的 RegEx 来告诉 SED 打印特定行。

sed -n '/regex1/,/regex2/p' INPUT_FILE > NEW_FILE

或者,你也可以给下面的单行

sed '/regex1/,/regex2/!d' INPUT_FILE > NEW_FILE

使用重定向运算符>,您可以创建文件的子集。

对于在 AWK 中拆分文件,如果您知道文件中的记录数 (wc -l < INPUT_FILE),那么您可以这样写 -

awk 'NR==2,NR==5' INPUT_FILE

NR 是 AWK 的内置变量,它被设置为记录的行号。所以如果你有一个 1500 行的文件并且只需要前 750 行,那么你可以做这样的事情 -

awk 'NR==1,NR==750' INPUT_FILE

如前所述,您可以但不必在 AWK 中提及 print。只要您的模式是真实的,它就会为您服务。

尽管您的文件中有一百万行,但这将是一个很大的痛苦。所以下面的 AWK 单线应该可以解决问题。

awk '{print >("SMALL_BATCH_OF_FILES_" int((NR+2)/3))}' BIG_INPUT_FILE

这一行将创建 SMALL_BATCH_OF_FILES_,每行包含 3 行。您可以将其设置为您的舒适度。 (NR+2/3)

执行:

[jaypal~/Temp]$ cat BIG_INPUT_FILE 
1
2
3
4
5
6
7
8
9
10

[jaypal~/Temp]$ awk '{print >("SMALL_BATCH_OF_FILES_" int((NR+2)/3))}' BIG_INPUT_FILE

[jaypal~/Temp]$ ls -lrt SMALL*
-rw-r--r--  1 jaypalsingh  staff  3 25 Nov 10:41 SMALL_BATCH_OF_FILES_4
-rw-r--r--  1 jaypalsingh  staff  6 25 Nov 10:41 SMALL_BATCH_OF_FILES_3
-rw-r--r--  1 jaypalsingh  staff  6 25 Nov 10:41 SMALL_BATCH_OF_FILES_2
-rw-r--r--  1 jaypalsingh  staff  6 25 Nov 10:41 SMALL_BATCH_OF_FILES_1

[jaypal~/Temp]$ cat SMALL_BATCH_OF_FILES_1 
1
2
3
[jaypal~/Temp]$ cat SMALL_BATCH_OF_FILES_2 
4
5
6
[jaypal~/Temp]$ cat SMALL_BATCH_OF_FILES_3
7
8
9
[jaypal~/Temp]$ cat SMALL_BATCH_OF_FILES_4
10

【讨论】:

  • 感谢您提供大量示例的详尽回答。干杯!
【解决方案2】:

perl -ne 'print if /start pattern/ .. /end pattern/' 将打印 任何 行序列,该序列以匹配 /start pattern/ 的行开头并以匹配 /end pattern/ 的行结束。如果你想在第一个这样的块之后退出,你可以使用perl -ne 'print if /start pattern/ .. 0; last if /end pattern/'

第一个也可以在awk中完成:/start pattern/, /end pattern/ { print }

第二个大概也可以在awk中完成,但是我不太了解awk。

【讨论】:

    【解决方案3】:

    只是已经建议的解决方案的一个示例

    awk '/regexp1/,/regexp2/'
    

    假设你的输入文件是

    0 zzz
    1 aaa
    2 bbb
    3 ccc
    4 aaa
    5 ddd
    6 ccc
    7 aaa
    8 ddd
    9 eee
    10 ddd
    11 zzz
    

    命令

    awk '/a/, /d/' file.txt
    

    将提取两个子集:第 1 到 5 行(注意 4 aaa 被忽略)和第 7 到 8 行(注意 10 ddd 被忽略)

    1 aaa
    2 bbb
    3 ccc
    4 aaa
    5 ddd
    7 aaa
    8 ddd
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-21
      • 1970-01-01
      • 2017-10-03
      • 1970-01-01
      • 2011-09-02
      相关资源
      最近更新 更多