Bash:逐行遍历文件,找到特定的字符串并附加到每个后续行,直到找到相同的字符串

Posted

技术标签:

【中文标题】Bash:逐行遍历文件,找到特定的字符串并附加到每个后续行,直到找到相同的字符串【英文标题】:Bash: loop through file line by line, find specific string and append to each subsequent line until same string is found 【发布时间】:2013-07-28 17:18:48 【问题描述】:

我通常使用具有唯一标识符的原始文件或 csv 文件,这些标识符可以在各种数学程序中使用。最近,我得到了一个文件文件夹,其中将记录相互匹配的唯一方法是通过它们在文本文件中的位置。

这是一个示例 File01.txt:

AA1000   
AA2222        
AB1X6110305126101234760ABA08B88                   ZZ1111110000  
AB2X611030512612006100901C109Z 001110001110                                    
AB2X611030512612006100901X571Z 007410000000                                                                   
AB1X6110305127101234760ABA10B89                   ZZ1111110022  
AB2X611030512712006101001A571Z 007410000000                                  
AB1X6110305128101234760ABA10C00                   ZZ1111110055  
AB2X611030512812006101001A571Z 007410007410                                    
AC11

第 3 行以 AB1 开头,第 4-8 行以 AB2 开头,对应于第 3 行,如从该行第 4 位开始的 12 个字符串所示。该 12 个字符的字符串是匹配集群的唯一方法,但它不一定在所有行中都是唯一的。要知道 4-8 中的 AB2 组对应于第 3 行中的 AB1 组的唯一方法是第 4-8 行跟随第 3 行。对于像我这样的非程序员来说,这是一场噩梦。

我想做的是在 File01.txt 中读取并逐行循环,直到遇到 AB1 行。我想存储 AB1 线,然后继续循环。一条 AB1 线后面总是至少有一条 AB2 线。我想将 AB2 行写入数组并从内存中附加 AB1 行,然后继续循环并写入数组,直到遇到新的 AB1 行。新的 AB1 行现在将存储在内存中,并按照上述方式执行直到下一个 AB1 行,依此类推,直到到达文件末尾(通常是 AC11 行)

我希望输出文件看起来像这样:

AB2X611030512612006100901C109Z 001110001110    AB1X6110305126101234760ABA08B88                   ZZ1111110000                            
AB2X611030512612006100901X571Z 007410000000    AB1X6110305126101234760ABA08B88                   ZZ1111110000                                                         
AB2X611030512712006101001A571Z 007410000000    AB1X6110305127101234760ABA10B89                   ZZ1111110022                                 
AB2X611030512812006101001A571Z 007410007410    AB1X6110305128101234760ABA10C00                   ZZ1111110055    

虽然不理想,但我可以使用这种类型的数据并拆分字符串等。这是否可以使用 bash 和 awk 或 sed 之类的东西?

提前感谢您提供的任何帮助/见解。

【问题讨论】:

【参考方案1】:

如果我满足您的要求,这个小 awk 程序就可以工作:

awk '/^AB1/ab1=$0;next/^AB2/print $0, ab1'

这不会对不以 AB1 或 AB2 开头的任何行执行任何操作,并且它无法检查 AB1/AB2 后面的 12 个字符的字符串是否相等。我不知道你是否需要那张支票。

【讨论】:

感谢您的帮助。抱歉,我不清楚是否需要支票。我不。我只需要能够运行一些命令,这些命令将通过文本文件创建带有信息列表的新文件。我将如何运行这个 awk 命令? awk file01.txt 然后是上面的命令并将其传送到一个新文件? @FocusedEnergy:那么该命令应该可以工作(您需要添加文件名,当然:awk '/...' file01.txt 谢谢你。我认为我非常接近。我运行了命令,输出文件有一个 AB2 行,后跟一个 AB1 行。是否可以在 AB2 所在的同一行打印 $0,以便将其作为一行数据导入? $0 是 AB2 行,print $0, ab1 不引入换行符。可能您看到换行符是因为该行对于您的终端来说太长了?通常,awk 在print 的参数之间放置一个制表符;如果您更喜欢其他内容,可以写,例如:print $0 " " ab1print $0 " | " ab1 您好 rici,再次感谢您的跟进。我更改了分隔符,它仍然出现在单独的行上。我必须在文件中有一些我无法辨认的东西(或者多个空格破坏了某些东西)。我上面提供的示例是确切的间距。如果我复制该输出并运行您的 awk 命令,我总是以 AB2 行之后的 AB1 行结束,但从不在同一行上。有没有办法强制连接?根据我的理解,“,”就是这样做的,所以它应该像你写的那样工作。【参考方案2】:

这可能对你有用(GNU sed):

sed -r '/^AB1/!d;$!N;/\nAB2/!D;s/\s+$/ /;s/(.*)\n(.*)/\2\1\n\1/;P;D' file

提供的示例中的间距似乎有点不合理,因此我将其缩小为一个空格。

【讨论】:

谢谢波东。我在 Mac 上运行 BSD sed,“-r”似乎根本不起作用。我认为你是对的,间距可能会导致问题(这就是我要开始的),如果我能处理间距,希望我能把这些线连接起来。很多年前的某个人没有想到。此类数据中没有唯一标识符?疯狂! :)

以上是关于Bash:逐行遍历文件,找到特定的字符串并附加到每个后续行,直到找到相同的字符串的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法从 ASC 文件中逐行读取并在特定子字符串后检查它?

Erlang - 在外部文件中搜索特定字符串,如果不存在则追加文件

Bash:查找包含特定字符串的文件并将它们复制到文件夹中

在 bash 上逐行读取文件;每一行都包含另一个 unqiue 文件的路径

使用for循环bash脚本逐行读取文件[重复]

for 使用 Bash 遍历目录中的特定文件