首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用'awk'/Python删除重复的函数块(通用解决方案)

使用'awk'/Python删除重复的函数块(通用解决方案)
EN

Stack Overflow用户
提问于 2018-03-16 12:33:58
回答 5查看 153关注 0票数 3

我有一个包含几个函数块的文本文件,其中一些是重复的。我想要创建一个只包含唯一功能块的新文件。例如input.txt (我已经更新了示例):

代码语言:javascript
复制
Func (a1,b1) abc1
{
xyz1;
    {
        xy1;
    }

xy1;
}

Func (a2,b2) abc2
{
xyz2;
    {
        xy2;
        rst2;
    }

xy2;
}

Func (a1,b1) abc1
{
xyz1;
    {
        xy1;
    }

xy1;
}

Func (a3,b3) abc3
{
xyz3;
    {
        xy3;
        rst3;
        def3;
    }

xy3;
}
    Func (a1,b1) abc1
{
xyz1;
    {
        xy1;
    }

xy1;
}

并希望将output.txt设置为:

代码语言:javascript
复制
Func (a1,b1) abc1
{
xyz1;
    {
        xy1;
    }

xy1;
}

Func (a2,b2) abc2
{
xyz2;
    {
        xy2;
        rst2;
    }

xy2;
}

Func (a3,b3) abc3
{
xyz3;
    {
        xy3;
        rst3;
        def3;
    }

xy3;
}

我找到了一个使用awk删除重复行的解决方案,如下所示:

代码语言:javascript
复制
$ awk '!a[$0]++' input.txt > output.txt

但问题是,上面的解决方案只匹配一行,而不是文本块。我想将这个awk解决方案与regex结合起来,以匹配一个函数块:'/^FUNC(.|\n)*?\n}/'

但我没能做到。任何建议/解决办法都会很有帮助。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2018-03-21 17:21:50

感谢大家的解决方案。根据我发布的示例,它们是正确的,但我的实际任务更通用一些。我在Python中找到了一个通用的解决方案,因为上面提到的响应并不完美(可能是因为我对bash的了解有限)。我使用Pythons的通用解决方案如下:

代码语言:javascript
复制
import re
import os

testFolder = "./Path"

#Usage: Remove duplicate function block from one or more .txt files available in testFolder

#Iterating through the list of all the files available
for testFilePath in os.listdir(testFolder):
    if testFilePath.endswith(".txt"):
        #Extracting path for each text file found
        inputFile = open (testFolder + "/" + testFilePath, "r")

        #Creating a reduced folder in the output path
        outputPath = testFolder + "/Reduced"
        if not os.path.exists(outputPath):
            os.makedirs(outputPath)
        outputFile = open (outputPath + "/" + testFilePath, "w")

        #Reading all the content into a single string
        fileContent = inputFile.read()

        #Pattern for matching a Function block. Pattern matches multiple lines
        pattern = re.compile('(^FUNC(.|\n)*?\n})*',re.M)

        # Creating a list of function blocks
        funcList = pattern.findall(fileContent)
        #Creating a list of unique function block, thus removing duplicate data
        uniqueFuncList = set(funcList)

        #Writing each Function block to the output file separeted by a new line
        for element in uniqueFuncList:
            outputFile.write(element[0] + "\n\n") 
        inputFile.close()
        outputFile.close()
票数 0
EN

Stack Overflow用户

发布于 2018-03-16 13:12:29

代码语言:javascript
复制
$ awk '$1=="Func"{ f=!seen[$NF]++ } f' file
Func (a1,b1) abc1
{
xyz1;
    {
        xy1;
    }

xy1;
}

Func (a2,b2) abc2
{
xyz2;
    {
        xy2;
        rst2;
    }

xy2;
}

Func (a3,b3) abc3
{
xyz3;
    {
        xy3;
        rst3;
        def3;
    }

xy3;
}

以上只是假设每个Func定义都在它自己的行上,该行以函数名结尾。

它所做的就是查找一个"Func“行,然后将一个标志f设置为true,如果这是我们第一次在行尾看到函数名,否则则为false (使用常见的awk成语!seen[$NF]++,您已经在您的问题中使用了它,但将其命名为a[])。然后,如果f为true,则打印当前行(即,您遵循以前未见函数名的Func定义),并跳过它(也就是说,您遵循前面看到的函数名的Func定义)。

票数 5
EN

Stack Overflow用户

发布于 2018-03-16 12:39:59

如果代码块用空行分隔,则可以定义记录分隔符(和输出记录分隔符).

代码语言:javascript
复制
$ awk -v RS= -v ORS='\n\n' '!a[$0]++' input.txt > output.txt

NB.处理玩具示例,但是这是脆弱的,因为代码块中的任何空行都会破坏逻辑。类似地,您不能依赖于大括号,因为它也可能出现在代码块中。

更新

对于更新的输入,这样可以更好地工作。

代码语言:javascript
复制
$ awk -v ORS='\n\n' '{record=($1~/^Func/)?$0:record RS $0} 
    /^}/ && !a[record]++{print record} '

在这里,我们定义了以"Func“关键字开头的记录,并以第一个位置上的大括号结尾。为记录积累行并打印“已完成”。将ORS设置为在记录之间有空行。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49320913

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档