通过 AWK 或脚本进行文本处理来管理大文件

通过 AWK 或脚本进行文本处理来管理大文件

回答@Ed Morton,

输入

...
useless_words Number_100 : Message xx Dublin xx Paris useless_words -Code 452 useless_words
useless_words Number_100 : Rename message (old 452 ; new 557)
useless_words Number_100 : Message xx Dublin xx Paris useless_words -Code 557 useless_words
useless_words Number_101 : Message xx Toronto xx Rio useless_words -Code 842 useless_words
useless_words Number_102 : Message xx Rome xx Moscow useless_words -Code 432 useless_words
useless_words Number_103 : Message from Dublin to Paris -Code 557
useless_words Number_103 : Error Message
...
useless_words Number_110 : Message xx Alger xx Barcelona useless_words -Code 345 useless_words
useless_words Number_110 : Rename message (old 345 ; new 846)
useless_words Number_110 : Message xx Alger xx Barcelona useless_words -Code 846 useless_words
useless_words Number_111 : Message xx Mexico xx Dallas useless_words -Code 498 useless_words
useless_words Number_112 : Rename message (old 432 ; new 245)
...
useless_words Number_115 : Message from Alger to Barcelona -Code 846
useless_words Number_115 : Error Message
...

输出

useless_words Number_100 : Message xx Dublin xx Paris useless_words -Code 452 useless_words
useless_words Number_100 : Message xx Dublin xx Paris useless_words -Code 557 useless_words
useless_words Number_100 : Message from Dublin to Paris -Code 557
useless_words Number_110 : Message xx Alger xx Barcelona useless_words -Code 345 useless_words
useless_words Number_110 : Message xx Alger xx Barcelona useless_words -Code 846 useless_words
useless_words Number_110 : Message from Alger to Barcelona -Code 846

为了做到这一点,我想遵循以下步骤。

    1. 我匹配包含错误消息的行 => 我得到消息编号(此处为 Number_103 和 Number_115)
    1. 我搜索包含数字(Number_103 和 Number_115)的行,并选择 3 个单词(在本例中 $6 $8 $10 => Dublin Paris 557;Alger Barcelona 846)。我打印该行。我收到第一条消息。
    1. 我搜索与这 3 个单词匹配的行,并记下消息编号(此处为 Number_100 和 Number_110)。我打印这一行。我收到第二条消息。
    1. 我搜索与最后打印的消息具有相同消息编号的重命名消息(此处为 Number_100 和 Number_110),并得到旧密钥(此处为 345 和 452)
    1. 我通过旧密钥(此处为 345 和 452)和消息编号(此处为 Number_100 和 Number_110)搜索要打印的最后一条消息
    1. 我修改打印的第一条消息的消息编号(Number_103 -> Number_100; Number_115 -> Number_110)

我写的是

#!bin/bash
            
    grep -B1 'Error' inputs.txt |sed '/^-/d' | sed '/^$/d' | grep -v Error >> tmp_01.txt
    
    while read line
    do  
    
    read a b c <<< $(echo $line | cut -d' ' -f6,8,10)
    
    awk -v a1="$a" -v a2="$b" -v a3="$c" '$0~a1 && $0~a2 && $0~a3' inputs.txt >> tmp_02.txt
    
    done < tmp_01.txt
    
    awk '{++i} i==1 {a=$2} i==2 {$2=a; i=0} 1' tmp_02.txt
    
    rm -f tmp_*.txt

我明白了

useless_words Number_100 : Message xx Dublin xx Paris useless_words -Code 557 useless_words
useless_words Number_100 : Message from Dublin to Paris -Code 557
useless_words Number_110 : Message xx Alger xx Barcelona useless_words -Code 846 useless_words
useless_words Number_110 : Message from Alger to Barcelona -Code 846

我尝试快速获取代码,感谢 Bodo 的帮助!

实际上,我有一条消息发送到一个 BOX,该消息又发送到另一个地方(它们具有相同的 Number_)。

useless_words Number_100 : Message xx Dublin xx Paris useless_words -Code 452 useless_words

useless_words Number_100 : Rename message (old 452 ; new 557)

useless_words Number_100 : Message xx Dublin xx Paris useless_words -Code 557 useless_words

然后,我发送了一个 ACK​​ 直到 BOX(具有不同的 Number_)。

useless_words Number_103 : Message from Dublin to Paris -Code 557

通常情况下,BOX 收到的此 ACK 会发送到其他 BOX,但有时此 ACK 会被阻止,这就是我收到错误消息时的情况。

useless_words Number_103 : Error Message

答案1

根据修改后的问题和评论中的要求,此答案是尝试创建一个更快的脚本,该脚本产生与问题中的脚本相同的结果,而不修复其他问题。

建议的脚本将只处理输入文件两次,与错误消息的数量无关。

我不确定这是修改以获得问题中显示的输出的更好基础。 (有一条规则“首先要让它工作,而不是让它快速,而不是相反。”)

grep -B1 'Error' file.txt |sed '/^-/d' | sed '/^$/d' | grep -v Error| awk '{printf "/%s/ && /%s/ && /%s/\n", $6, $8, $10}' > filter.awk
awk -f filter.awk file.txt

或者不将awk脚本写入文件

awk -f <(grep -B1 'Error' file.txt |sed '/^-/d' | sed '/^$/d' | grep -v Error| awk '{printf "/%s/ && /%s/ && /%s/\n", $6, $8, $10}') file.txt

或不使用grep(并且没有任何等效的命令,sed这对于示例输入来说似乎是不必要的)

awk -f <(awk '/Error/ && prev {$0=prev;printf "/%s/ && /%s/ && /%s/\n", $6, $8, $10;next} {prev=$0}' file.txt) file.txt

答案2

在问题中的示例输入更改后,此处的解决方案不再有效。需要澄清。

输入格式的规范不明确。

根据问题的原始示例输入,此脚本将打印预期的输出。

awk '/Number_[0-9]* : Message .* -Code [0-9]* ./ { if($2 != first) i=0; line[i++]=$0; first=$2;}
/Number_[0-9]* : Message from .* -Code [0-9]*$/ { second=$2; sub(second,first); line[i++]=$0}
/Number_[0-9]* : Error Message/ && (second==$2) { print line[0]; print line[1]; print line[2];}' input

-Code该脚本通过在第一种情况下后面的数字和第二种情况下行尾的数字后面期望有一个空格和任何字符来区分第一种情况和第二种情况。

原始输入是

...
useless_words Number_98 : useless message
useless_words Number_99 : useless message
useless_words Number_100 : Message xx Dublin xx Paris useless_words -Code 452 useless_words
useless_words Number_100 : Rename message (old 452 ; new 557)
useless_words Number_100 : Message xx Dublin xx Paris useless_words -Code 557 useless_words
useless_words Number_101 : useless message
useless_words Number_102 : useless message
useless_words Number_103 : Message from Dublin to Paris -Code 557
useless_words Number_103 : Error Message
...
useless_words Number_110 : Message xx Alger xx Barcelona useless_words -Code 345 useless_words
useless_words Number_110 : Rename message (old 345 ; new 846)
useless_words Number_110 : Message xx Alger xx Barcelona useless_words -Code 846 useless_words
useless_words Number_111 : useless message
...
useless_words Number_115 : Message from Alger to Barcelona -Code 846
useless_words Number_115 : Error Message
...

输出

useless_words Number_100 : Message xx Dublin xx Paris useless_words -Code 452 useless_words
useless_words Number_100 : Message xx Dublin xx Paris useless_words -Code 557 useless_words
useless_words Number_100 : Message from Dublin to Paris -Code 557
useless_words Number_110 : Message xx Alger xx Barcelona useless_words -Code 345 useless_words
useless_words Number_110 : Message xx Alger xx Barcelona useless_words -Code 846 useless_words
useless_words Number_110 : Message from Alger to Barcelona -Code 846

问题修改后编辑

该脚本不再适用于修改后的输入,因为“无用行”现在具有与可能有趣的行相同的格式。

要修复此脚本,要么需要一个标准来区分可能有趣的行和无用的行,要么脚本必须存储多于一组的行,直到Error Message找到带有 的行。

我要求澄清这个问题。

相关内容