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 " " ab1
或 print $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 - 在外部文件中搜索特定字符串,如果不存在则追加文件