我有一个包含几个函数块的文本文件,其中一些是重复的。我想要创建一个只包含唯一功能块的新文件。例如input.txt (我已经更新了示例):
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设置为:
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删除重复行的解决方案,如下所示:
$ awk '!a[$0]++' input.txt > output.txt但问题是,上面的解决方案只匹配一行,而不是文本块。我想将这个awk解决方案与regex结合起来,以匹配一个函数块:'/^FUNC(.|\n)*?\n}/'。
但我没能做到。任何建议/解决办法都会很有帮助。
发布于 2018-03-21 17:21:50
感谢大家的解决方案。根据我发布的示例,它们是正确的,但我的实际任务更通用一些。我在Python中找到了一个通用的解决方案,因为上面提到的响应并不完美(可能是因为我对bash的了解有限)。我使用Pythons的通用解决方案如下:
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()发布于 2018-03-16 13:12:29
$ 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定义)。
发布于 2018-03-16 12:39:59
如果代码块用空行分隔,则可以定义记录分隔符(和输出记录分隔符).
$ awk -v RS= -v ORS='\n\n' '!a[$0]++' input.txt > output.txtNB.处理玩具示例,但是这是脆弱的,因为代码块中的任何空行都会破坏逻辑。类似地,您不能依赖于大括号,因为它也可能出现在代码块中。
更新
对于更新的输入,这样可以更好地工作。
$ awk -v ORS='\n\n' '{record=($1~/^Func/)?$0:record RS $0}
/^}/ && !a[record]++{print record} '在这里,我们定义了以"Func“关键字开头的记录,并以第一个位置上的大括号结尾。为记录积累行并打印“已完成”。将ORS设置为在记录之间有空行。
https://stackoverflow.com/questions/49320913
复制相似问题