【问题标题】:Awk scripting help - Logic Issueawk 脚本帮助 - 逻辑问题
【发布时间】:2010-09-14 15:17:45
【问题描述】:

我目前正在编写一个简单的 .sh 脚本来解析 Exim 日志文件中匹配“o”的字符串。目前,在查看 output.txt 时,每行(606 行)上都打印一个 0。我猜我的逻辑是错误的,因为 awk 不会抛出任何错误。

这是我的代码(针对串联和计数器问题进行了更新)。编辑:我从 dmckee 的回答中采用了一些新代码,我现在正在使用这些新代码而不是旧代码,以简化操作。

awk '/o'\''/ {
         line = "> ";
         for(i = 20; i <= 33; i++) {
           line = line " " $i;
         }
         print line;
    }' /var/log/exim/main.log > output.txt

有什么想法吗?

编辑:为了清楚起见,我在电子邮件地址中使用“o”,因为 ' 是电子邮件地址中的非法字符(在我们的数据库中,仅以 o' 为前缀的名称出现)。

编辑 2:根据评论要求,这里是一些所需输出的经过消毒的样本:

[xxx.xxx.xxx.xxx] kathleen.o'toole@domain.com <kathleen.o'toole@domain.com> routing defer (-51): retry time not reached

[xxx.xxx.xxx.xxx] julie.o'brien@domain.com <julie.o'brien@domain.com> routing defer (-51): retry time not reached

[xxx.xxx.xxx.xxx] james.o'dell@domain.com <james.o'dell@domain.com> routing defer (-51): retry time not reached

[xxx.xxx.xxx.xxx] daniel_o'leary@domain.com <aniel_o'leary@domain.com> routing defer (-51): retry time not reached

我在循环中从 20 开始的原因是因为第 20 字段之前的所有内容都只是标准日志信息,我在这里不需要这些信息。我所需要的只是此解决方案的 IP 及其他所有内容(每个 550 错误的消息对于每个正在使用的邮件服务器都不同。我正在编制一个常见的列表)

【问题讨论】:

  • 原始日志文件中有一行吗?
  • 我必须审查它(那里的敏感数据),但这里有一个:2008-09-28 04:50:43 1KisKj-0000tX-L0 == james.o'stuff@domain .org 路由延迟(-51):未达到重试时间
  • 如果你提供一个经过清理的示例文件(几行代码)和所需的输出,我将是你可以获得十几个免费的 perl、python 和 ruby​​ 解决方案,这些解决方案比这简单得多.
  • 您是否尝试从匹配 'o' 的每一行中获取 20-33 个字符
  • 啊,你是对的。我刚刚意识到第 20-33 行的概念是从我正在编写的类似脚本中继承而来的,该脚本是针对较长行的错误而设计的。我会尝试扩大它的边界。

标签: scripting awk logic


【解决方案1】:

+ 表示 awk 中的数字加法。如果要连接,只需将常量和/或表达式用空格分隔即可。

所以,这个

line += " " + $i

应该变成

line = line " " $i

编辑:Iff exim 日志文件(我更喜欢 Postfix :) 由单个空格分隔,以下不是更简单:

grep -F o\' /var/log/exim/main.log | cut -d\  -f20-33 >output.txt

?

【讨论】:

    【解决方案2】:

    这里不需要 grep。让 awk 为您选择匹配行(并根据 ΤZΩΤZΙΟΥ 修复您的串联错误):

    awk '/o'\''/ {
                 line = "> ";
                 for(i = 20; i <= 33; i++) {
                   line = line " " $i;
                 }
                 print line;
            }' /var/log/exim/main.log > output.txt
    

    当然,如果你像上面那样在提示符下进行,你最终需要一些奇怪的转义。它在脚本中更干净......


    编辑:第一遍我错过了 += 问题...

    还假设您上面给出的行是部分的,因为它只有 13 个字段(默认情况下,字段以空格分隔)。

    【讨论】:

    • 我试过了,在清除 output.txt 文件后,我仍然只是得到一堆 0。
    • 你是对的。请参阅我对这个问题的最后评论,了解原因。我已经相应地更新了我的代码。
    • 是的!有用。我所要做的就是在采用您的代码后扩大 for 循环。在文件上直接使用 awk 而不是通过 grep 和其他东西管道它要简单得多。谢谢。
    【解决方案3】:

    "'" 在本地不是非法的。来自RFC2821,第 4.1.2 节:

    Local-part = Dot-string / Quoted-string
    
    Dot-string = Atom *("." Atom)
    
    Atom = 1*atext
    

    2821 进一步引用 RFC2822 用于非本地定义的元素,因此:

    atext           =       ALPHA / DIGIT / ; Any character except controls,
                            "!" / "#" /     ;  SP, and specials.
                            "$" / "%" /     ;  Used for atoms
                            "&" / "'" /
                            "*" / "+" /
                            "-" / "/" /
                            "=" / "?" /
                            "^" / "_" /
                            "`" / "{" /
                            "|" / "}" /
                            "~"
    

    换句话说,“'”是一个完全合法的不带引号的字符,包含在电子邮件本地部分中。现在,在您的网站上可能不合法,但这不是您所说的。

    很抱歉没有直接讨论主题,但我想更正你的说法。

    【讨论】:

      【解决方案4】:

      关闭任务,更简单:python。

      import fileinput
      for line in fileinput.input():
          if "'" in line:
              fields = line.split(' ')
              print "> ", ' '.join( fields[20:34] )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-08
        • 1970-01-01
        • 2011-03-07
        • 1970-01-01
        相关资源
        最近更新 更多