【问题标题】:Extract similar lines from multiple files in folder从文件夹中的多个文件中提取相似的行
【发布时间】:2019-06-21 06:57:21
【问题描述】:

我有一个目录,其中包含大约 30 个具有类似模式的 Python 文件,如下所示:

import stuff

class BarFoo001(BarFooBase):

    info = self.info
    description = 'here's the stuff I want'
    IS_CRITICAL = true

    def method(sdf):
        etc...

我想从每个文件中只提取带有类名和描述的行(只是作为参考的文本,我不需要工作的 Python 文件)。

我的第一个想法是用 shell 工具来做这件事。我用cat *.py > all.py,然后尝试sed -i -e 's/BarFooBase\(.*\)IS_CRITICAL/\1/' all.py,但这似乎没有效果。我也尝试在我的 IDE 中使用 RegEx,最后在 Python (re.sub('IS_CRITICAL[^>]+\nclass Bar', '', my_string)) 中使用,但这些都没有给我想要的结果。我的正则表达式有什么问题?另外,有没有我想念的更简单的方法来做到这一点?

这将是一个足够好的输出:

类 BarFoo001(BarFooBase):

信息 = self.info
description = '这是我想要的东西'
IS_CRITICAL

【问题讨论】:

    标签: python regex text awk sed


    【解决方案1】:

    试试这个,看看结果是不是你想要的(GNU awk):

    awk '/IS_CRITICAL/{sub(/IS_CRITICAL.*/,"IS_CRITICAL");print "class " $0}' RS="class " all.py
    

    【讨论】:

    • 谢谢,快到了!但它只返回 class IS_CRITICAL 而没有中间文本(这是我真正需要的,实际上我不需要描述字符串)
    • 现在它打印class ountReasons.REASON X class ountReasons.REASON Y IS_CRITICAL 等...它只是在每行之前打印class 吗?
    【解决方案2】:

    使用sed,你可以使用地址范围来输出行的块:

    sed -n '/^[[:blank:]]*class[[:blank:]]/,/IS_CRITICAL/p' file.py
    

    编辑:

    class 之前和之后添加了[[:blank:]],以仅匹配前面有零个或多个空格或制表符的类定义。

    【讨论】:

    • 另一个很棒的事情是我可以将description 换成IS_CRITICAL 并得到我想要的确切行,这是其他答案不允许的
    【解决方案3】:

    请您尝试以下操作。它应该在所有类型的awk 版本中运行,但无法在所有版本或不同的操作系统系统中进行测试。

    awk '
    {
      sub(/^ +/,"")
    }
    /class/{
      found=1
    }
    /IS_CRITICAL/ && found{
      sub(/ =.*/,"")
      print
      found=""
    }
    found
    '  Input_file
    

    【讨论】:

    • @Josh Friedlander,你能不能也检查一下上面,让我们知道。
    • 它有效 - 使用 sed 提供与 SLePort 的答案相同的输出。谢谢!
    • @Ed Morton,根据您的好建议使用了found 变量(代替我的旧习惯flag),请在您看到改进的地方继续纠正我,干杯。
    • @EdMorton,我总是对这个文件打开错误感到困惑,感谢您的澄清,会记下它。现在改了。
    【解决方案4】:

    使用 Perl 单行代码

     perl -0777 -ne ' while( /(\bclass\s*.+?IS_CRITICAL)/gs ) { print "$1\n" } ' 
    

    有输入:

    $ cat josh.py
    import stuff
    
    class BarFoo001(BarFooBase):
    
        info = self.info
        description = 'here's the stuff I want'
        IS_CRITICAL = true
    
        def method(sdf):
            etc...
        def method2(fddf):
            print
    $ perl -0777 -ne ' while( /(\bclass\s*.+?IS_CRITICAL)/gs ) { print "$1\n" } ' josh.py
    class BarFoo001(BarFooBase):
    
        info = self.info
        description = 'here's the stuff I want'
        IS_CRITICAL
    $
    

    要搜索多个文件,可以使用

    perl -0777 -ne ' while( /(\bclass\s*.+?IS_CRITICAL)/gs ) { print "$ARGV:$1\n" } ' *py
    

    【讨论】:

    • 是的..当你想跨行匹配时,/s 修饰符会做这些事情..你也可以将多个文件传递给脚本..比如 *py
    • 对于我觉得难以理解的编程语言,我可能会使用与“令人难以置信”不同的词。不过加入俱乐部 - zoitz.com/archives/13.
    • @Ed,这只是开始麻烦.. 我希望你能尝试
    • 我只是觉得听到人们对他们无法理解的代码感到敬畏而不是表达他们对它的恐惧感到沮丧。您对复杂的 sed 脚本得到相同的响应。我个人还没有找到 perl 的用途,但是当它出现时,我会尝试一下。实际上,当我想要一个 strptime() 函数时,我想我确实找到了它的用途。我见过人们写清晰的 perl,这似乎不是惯用的规范。
    【解决方案5】:
    $ grep -E '^[[:space:]]*(class|description)[[:space:]]' file
    class BarFoo001(BarFooBase):
        description = 'here's the stuff I want'
    
    $ awk 'sub(/^[[:space:]]*(class|description =)[[:space:]]+/,"")' file
    BarFoo001(BarFooBase):
    'here's the stuff I want'
    

    【讨论】:

    • 太好了,它也删除了空白行
    猜你喜欢
    • 1970-01-01
    • 2023-02-05
    • 2020-11-20
    • 2020-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多