【问题标题】:Uncertain separator, parsing a messy log with sed不确定的分隔符,用 sed 解析杂乱的日志
【发布时间】:2011-03-07 02:02:00
【问题描述】:

我正在处理#huge# 文本文件(从 100mb 到 1gb),我必须解析它们以提取一些特定的数据。令人讨厌的是文件没有明确定义的分隔符。

例如:

"element" 123124 16758 "12.4" "element" "element with white spaces inside" "element"

我必须删除受“(引号)限制的字符串中的空格,问题是我不能删除引号“外部”的空格(否则某些数字会合并)。 我找不到合适的 sed 解决方案,有人可以帮我解决这个问题吗?

【问题讨论】:

    标签: sed text-parsing


    【解决方案1】:

    我想不出一个 sed 解决方案,但是您最好只编写一个小应用程序来执行此操作。

    #include <iostream>
    #include <string>
    using namespace std;
    
    int main() {
        string line;
        while(getline(cin,line)) {
            bool inquot = false;
            for(string::iterator i = line.begin(); i != line.end(); i++) {
                char c = *i;
                if (c == '"') inquot = !inquot;
    
                if (c != ' ' || !inquot) cout << c;
            }
            cout << endl;
        }
        return 0;
    }
    

    那就去吧

    ./a.out &lt; test.log &gt; new.out

    免责声明

    如果您在行上转义了引号或引号内的多行内容,这将完全窒息。

    例如 "The word \"word\" is weird" 和这样的事情会导致问题

    【讨论】:

      【解决方案2】:

      和 Jamie 一样,我认为 sed 不适合这份工作。可能是我的 sed 技能不足以胜任这项工作。这是一个与 Jamie 基本相同的解决方案,但在 Python 中:

      #!/usr/bin/env python
      
      # Script to delete spaces within the double quotes, but not outside.
      
      QUOTE = '"'
      SPACE = ' '
      
      file = open('data', 'r')
      for line in file:
          line = line.rstrip('\r\n')
          newline = ''
          inside_quote = False
          for char in list(line):
              if char == QUOTE:
                  inside_quote = not inside_quote
              if not (char == SPACE and inside_quote):
                  newline += char
          print(newline)
      file.close()
      

      将此脚本保存到文件中,例如 rmspaces.py。然后您可以从命令行调用脚本:

      python rmspaces.py
      

      请注意,脚本假定数据位于名为 data 的文件中。您可以修改脚本以适应口味。

      【讨论】:

        【解决方案3】:

        您使用 awk,而不是 sed。当然没有必要创建自己的 C 程序,因为awk 已经是一个出色的 C 程序来进行文件处理,即使在 GB 文件上也是如此。所以这里有一个班轮来完成这项工作。

        $ more file
        "element" 123124 16758 "12.4" "element" "element with white spaces inside" "element"
        
        $ awk -F'"' '{for(i=2;i<=NF;i+=2) {gsub(/ +/,"",$i)}}1' OFS='"' file
        "element" 123124 16758 "12.4" "element" "elementwithwhitespacesinside" "element"
        

        【讨论】:

        • 这解决了我的问题。只是最后一个请求,你能解释一下代码吗?非常感谢(我对 awk 不是很熟悉)
        • 通过设置双引号作为字段分隔符,引号内的单词的字段编号是偶数。因此,i 计数器增加 2。gsub() 将所有空格替换为 null。请阅读 gawk 手册(搜索 GNU awk)了解更多信息
        猜你喜欢
        • 2011-12-27
        • 1970-01-01
        • 1970-01-01
        • 2019-07-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多