Awk Unix提取两行之间的行,并将它们存储在各自的文件中

Awk Unix提取两行之间的行,并将它们存储在各自的文件中,awk,sed,grep,Awk,Sed,Grep,我在allreport.txt文件中有一个如下文件: 11:22:33:456 Script started Running: first_script 11:22:34:456 GetData - Read Read 12 Bytes 11:22:34:456 SetData - Write Write 12 Bytes 11:32:33:456

我在allreport.txt文件中有一个如下文件:

11:22:33:456        Script started                  Running: first_script
11:22:34:456        GetData - Read                  Read 12 Bytes
11:22:34:456        SetData - Write                 Write 12 Bytes
11:32:33:456        Script started                  Running: second_script
11:32:34:456        GetData - Read                  Read 12 Bytes
11:32:34:456        SetData - Write                 Write 12 Bytes
11:42:33:456        Script started                  Running: third_script
11:42:34:456        GetData - Read                  Read 12 Bytes
11:42:34:456        SetData - Write                 Write 12 Bytes
11:52:33:456        Script started                  Running: fourth_script
我的要求是,我需要提取位于“*脚本”之间的“…..”行。我尝试了以下方法:

grep 'Running:' allreport.txt | sed 's/[^ ]* //' | cut -d":" -f2 | tr '\n' ' ' | awk -v col=1 '/$col/,/$($col+1)/ allreport.txt  > $col'
但在执行命令后,我看到没有输出,也没有创建结果文件

如何实现相同的效果-预期的输出是包含第一个\u脚本、第二个\u脚本等文件,并且每个文件都包含其运行日志-示例第一个\u脚本应仅包含以下行:

11:22:34:456        GetData - Read                  Read 12 Bytes
11:22:34:456        SetData - Write                 Write 12 Bytes
类似地,第二个脚本应具有以下行,以此类推:

11:32:34:456        GetData - Read                  Read 12 Bytes
11:32:34:456        SetData - Write                 Write 12 Bytes

眼前的问题似乎是在Awk脚本的引号中有一些shell脚本代码。。。但更根本的是,你的脚本太复杂和怪异了

<代码> AWK '/Run:/{Calp(c);C++;下一} {print>c}'allreport.txt
$awk'sub(/.*运行:/,“”){close(out);out=$0;next}{print>out}'allreport.txt
$head*脚本

==>第一个脚本第二个脚本第三个脚本仅显示示例,请尝试以下内容。作为输出,它将创建3个文件,分别名为
first\u script
second\u script
third\u script
,并显示示例

awk -F': ' '/Running/{close(outFile);outFile=$2;next} {print > (outFile)}' Input_file

解释:简单的解释是,将字段分隔符设置为
,然后检查行中是否运行了
,然后将输出文件名设置为第二个字段。若该行未运行
,则将该行打印到输出文件中。还要确保在后端关闭输出文件,以避免此处出现“打开的文件过多错误”。

您也可以尝试此awk:

awk'$(NF-1)==“正在运行:{close(fn);fn=$NF;next}{print>fn}”文件
您可以使用该实用程序根据内容拆分文件:

csplit allrep.txt /[[:space:]]Running:[[:space:]]/ '{*}'
# produces xx00 - xxNN files based on that match
某些版本不支持
'{*}'
。如果是这种情况,则需要在
{}
中提供拆分的数量。你可以做:

csplit allrep.txt /[[:space:]]Running:[[:space:]]/ "{$(awk '/\sRunning:\s/{cnt++} END{print cnt-1}' allrep.txt)}" 
如果您想要文件名,我会在
awk
中这样做:

awk 'BEGIN{fn="0000 - Header"}
{sub(/\r$/,"")}   # the file you uploaded has \r\n endings
$(NF-1)=="Running:" {close(fn); fn=sprintf("%04d - %s.txt", ++fc, $NF)}
{print >fn}
' allrep.txt

通过在前面添加一个数字,1)负责所有DUP,2)允许您查看顺序。

我在下面看到错误“awk:cmd.line:1:(FILENAME=allreport.txt FNR=1)致命:用于`>'重定向的表达式的字符串值为空。我们可以为输出使用一个常量文件名,然后像script1.log、script2.log等等。稍后我可以重命名它们。哦,糟糕,这看起来像是移动设备上的两行。现在更新了。谢谢,但我收到一个错误“awk:cmd”。第1行:(FILENAME=allreport.txt FNR=1)致命:用于`>'重定向的表达式具有空字符串值,那么您运行它所针对的输入看起来不像您提供的示例输入,或者您在复制/粘贴我提供的脚本时出错。根据您告诉我们的输入,我的答案中的脚本将生成您要求的输出,如我的答案所示。实际文件的头部分导致前几行写入空文件名。你需要一个默认值,用于
out
@dawg啊,我明白了,太糟糕了,OP没有在他们问题的示例输入/输出中包含这个值。我想知道他们是想让头出现在每个输出文件中,还是想被丢弃,还是想得到它自己的文件或其他东西。哦,好吧……不要提供链接或图片,只需创建并发布一个简洁、可测试的样本输入和预期输出,充分代表您问题中的真实数据。如果它太大,您无法发布和/或提供预期的输出,那么它肯定太大,无法让我们阅读。感谢上面提到的csplit命令帮助了我-非常感谢-但是是否可能将格式为xxNN的输出文件名命名为脚本名,如-first\u script等?不,直接从
csplit
中获取任意文件名不是一种简单的方法。然后,您可以使用Bash脚本读取第一行以获取文件名。然后,您需要在这里处理与
awk
解决方案相同的问题:dups呢?@Programmer:经常查看updateThanks-它解决了我的问题,非常感谢
awk 'BEGIN{fn="0000 - Header"}
{sub(/\r$/,"")}   # the file you uploaded has \r\n endings
$(NF-1)=="Running:" {close(fn); fn=sprintf("%04d - %s.txt", ++fc, $NF)}
{print >fn}
' allrep.txt