程序员将如何处理此文本处理任务?

时间:2014-11-26 21:24:02

标签: regex algorithm text text-processing

一些背景

我问的是程序员将如何处理这项任务,因为我不是真正的程序员。我是一名研究定量社会科学的研究生,虽然我一直在编程一年,但我没有接受过正式的培训。

我并不关心实现通用算法。我很高兴在Bash,AWK,R或Python中工作。我还在Java,C,JavaScript和Matlab中编写了一小段代码(超出“hello world”,但没有进一步说明)。但是,如果某种语言或语言的某些功能可以使这项任务更容易或更自然,我很乐意了解它。

相反,我对算法和数据结构很感兴趣。我该抓什么,何时抓住它,在哪里保存等等?我想我可以通过一些巧妙构造的正则表达式完成所有这些工作,而且我对中间级正则表达式功能(如外观)非常熟悉,但我自己编写的任何东西无疑都是hacky和ad-hoc。

任务

我所拥有的是代码(恰好在R中)看起来像这样,其中#表示注释:

items = list(
    day1 = list(
    # a apples
    # b oranges
    # c pears
    # d red grapes
    # m.
      # 1 peanuts
      # 2 cashews
        type1 = c("a", "b", "d", "m.2")  # this returns a vector of strings
        type2 = c("c", "m.1")
    ),                                   # this returns a list of vectors
    day2 = list(
    # a apples
    # b oranges
    # c pears
    # d red grapes
    # e plums
    # m.
      # 1 peanuts
      # 2 cashews
      # 3 pistachios
        type1 = c("a", "b", "d", "e", "m.2")
        type2 = c("c", "m.1", "m.3")
    )
)                                       # this returns a list of lists of vectors

而我想要的是代码看起来像这样:

items = list(
    day1 = list(
        type1 = c(
            "apples" = "a",
            "oranges" = "b",
            "red grapes" = "d",
            "cashews" = "m.2"
        ),
        type2 = c(
            "pears" = "c",
            "peanuts" = "m.1"
        )
    ),
    day2 = list(
        type1 = c(
            "apples" = "a", 
            "oranges" = "b",
            "red grapes" = "d",
            "plums" = "e",
            "cashews" = "m.2"
        ),
        type2 = c(
            "pears" = "c",
            "peanuts" = "m.1",
            "pistachios" = "m.3"
        )
    )
)

有些注意事项:

  1. 可以依赖该格式后的评论文字。
  2. 无法依赖day1的命名day2被“嵌套”在type的命名中。有些字母可能会互换。
  3. 可以依赖于day s内{{1}} s的相同数量和名称。
  4. 垂直间距不重要;我大多只是想把注释放到代码中,如图所示,虽然让脚本为我做的所有间距都会很好。
  5. 那么,程序员如何以编程方式将第一个代码段转换为第二个?我可以在大约15分钟的复制和粘贴中完成它,但我想在这里学到一些东西。而且,我不是要求预先编写代码,我只是在寻找一些方向,因为现在我只是在黑暗中摸索。

2 个答案:

答案 0 :(得分:1)

鉴于您的代码示例,通过将包含几个步骤的转换组合在一起,它应该是可行的。在较高的层次上,您需要将注释读入可以查询的数据集合,然后解析代码并执行查找/替换引用数据集合。

如果没有太深入,可能会看起来像:

  1. 生成仅包含评论的文本文件。使用具有&#34意图的正则表达式;找到以空格开头的所有行,然后是#" (类似^\s*#.*$)会给你一个结果,如:
  2. # a apples
    # b oranges
    # c pears
    # d red grapes
    # m.
      # 1 peanuts
      # 2 cashews
    # a apples
    # b oranges
    # c pears
    # d red grapes
    # e plums
    # m.
      # 1 peanuts
      # 2 cashews
      # 3 pistachios
    
    1. 使用上述结果,您可以利用一些基本的文本解析来细分每一行。处理m.个案需要一些假设。根据您的示例,我从一些伪代码开始,如:
    2. For each line
        Get the first character after the # and call it "key"
        Find the word after the letter and call it "value"
      
        If the key is a letter
          Add "key" => "value" to the dictionary
          Next line
      
        If the key is a number
          Get the last key added to the dictionary and call it as "parentkey"
          Add "parentkey"+"key" => "value" to the dictionary
          Next line
      

      这会给你一个像这样的结构:

      {
        "a": "apples",
        "b": "oranges",
        "c": "pears",
        "d": "red grapes",
        "m.": "",
        "m.1": "peanuts",
        "m.2": "cashews",
        "a": "apples",
        "b": "oranges",
        "c": "pears",
        "d": "red grapes",
        "e": "plums",
        "m.": "",
        "m.1": "peanuts",
        "m.2": "cashews",
        "m.3": "pistachios"
      }
      

      你可以清空空的" m。"通过迭代条目并删除具有空值的项目。

      1. 此时,您可以迭代字典并在代码文件中执行查找/替换:
      2. For each dictionary entry (key, value)
          Find strings like "key" and replace with strings like "value" = "key"
        

        总而言之,它并不是非常高效或优雅,但编码并不应该起作用。在那里可能需要考虑额外的细节(总是有)但是这样做是一个相当简单的方法。

答案 1 :(得分:0)

我会使用快速正则表达式替换来减少要做的工作,然后手动修复它。例如,你在那里过了一半:

s/# (\w+) ([\w ]+)/"\2" = "\1"/

要编写的确切正则表达式以及如何使用它取决于您的工具。不同的编辑器和编程语言是截然不同的。谷歌用于了解更多信息。 (您可能有多个简单选项 - Python命令行将使用一种语法,而vi编辑器则使用不同的语法。)

如果您必须定期执行此任务或获取更多代码,那么您需要了解解析。这项工作要多得多(如果你没有代码可以做到这一点,那就太值得了),但从长远来看也会更加强大。