我试图总结一张每天都在变化的数据表。我已经将该表汇总为仅显示条目大于 30 的行。
但是,有时原始表中的条目数不会超过 30 个。当发生这种情况时,我不需要摘要中的整个空白部分。然后我如何删除这些部分的整个标题?
理想情况下,如果所有 5 个部分中都没有条目,则不应打印任何行(或者只是打印一个字符串:“无:没有大于 30 的条目”,正如我试图做的那样)
包含 5 个部分的汇总表示例,summarished_output.txt:
=========================================================================================================
Month: Jun
Counter Name 06/04 18:00 06/04 17:00 06/04 16:00 06/04 15:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS. : 45 45 45 45
SYS.SYS.SYS.SYS.SYS.SYS. : 45 45 45 45
=========================================================================================================
Month: Jun
Counter Name 06/05 14:00 06/05 13:00 06/05 12:00 06/05 11:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS. : 45 45 45 45
SYS.SYS.SYS.SYS.SYS.SYS. : 45 45 45 45
=========================================================================================================
Month: Jun
Counter Name 06/05 10:00 06/05 09:00 06/05 08:00 06/05 07:00
=========================================================================================================
=========================================================================================================
Month: Jun
Counter Name 06/05 06:00 06/05 05:00 06/05 04:00 06/05 03:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS. : 45 45 45 45
SYS.SYS.SYS.SYS.SYS.SYS. : 45 45 45 45
=========================================================================================================
Month: Jun
Counter Name 06/04 18:00 06/04 17:00 06/04 16:00 06/04 15:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS. : 45 45 45 45
SYS.SYS.SYS.SYS.SYS.SYS. : 45 45 45 45
=========================================================================================================
正如您所看到的,第三部分是空的,因为original_output.txt 文件中没有高于30 的条目。但是标头仍然存在。
我的摘要代码(有效):
awk '$1=="Month:"||$1==""||$1=="Counter"||(index($1, "=")!=0)||$3>=30|| $4>=30 || $5>=30||$6>=30' original_output.txt>>summarised_output.txt
我尝试删除标题(不起作用):
touch summarised_output_temp.txt
awk '{if ($1=="Month:"||$1==""||$1=="Counter"||(index($1, "=")!=0)||$3>=30|| $4>=30 || $5>=30||$6>=30) print $0}' original_output.txt >> summarised_output_temp.txt
if (((wc -l < summarised_output_temp.txt)==42))
then
echo "None: there is no entry larger than 30" >> summarised_output.txt
else
cat output_7_temp.txt>>summarised_output.txt
fi
尝试收到的错误:
line 3: ((: (wc -l output_7_temp.txt | awk {print $1})==42: syntax error: invalid arithmetic operator (error token is ".txt | awk {print $1})==42")
答案1
如果你有 GNU awk
,你可以使用这个脚本:
awk -v RS='={105}[^=]*={105}' 'NF{print oRT,$0} {oRT=RT}' file
表头设置为多行记录分隔符RS
。它由两个 105 个字符以及中间的任何字符组成=
。
该变量RT
捕获每个记录的记录分隔符,并将其存储在变量中oRT
,并在下一条记录处打印,前提是有一些元素要打印(使用 catch 进行捕获NF
)。
答案2
创建可执行脚本test.awk,包含
awk '
# { print "read " $0 }
/^SYS/ {
if (H) {
if (F) {print F} else { F="\r\n\r\n"}
print H; H=""}
print
next
}
/^./ {
H=$0
for (i=1; i<5; i++) {
getline
H = H "\r\n" $0
}
next
}
' $@
并运行
test.awk original_output.txt
“/^SYS/ {”可以替换为任何可识别数据行的内容。
答案3
这个问题可以用 Perl 沿着这些思路来解决。
代码
perl -F'/^=+$/m' -lan -0777e '
my($dashes) = /^(=+)$/m;
shift @F; pop @F;
while ( @F > 1 ) {
my($h, $s) = splice @F, 0, 2;
next if $s =~ /^(?:\h*\n)+$/;
print join $dashes, q(), $h, $s, !@F ? q() : ();
}
' input.txt
输出
=========================================================================================================
Month: Jun
Counter Name 06/04 18:00 06/04 17:00 06/04 16:00 06/04 15:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS. : 45 45 45 45
SYS.SYS.SYS.SYS.SYS.SYS. : 45 45 45 45
=========================================================================================================
Month: Jun
Counter Name 06/05 14:00 06/05 13:00 06/05 12:00 06/05 11:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS. : 45 45 45 45
SYS.SYS.SYS.SYS.SYS.SYS. : 45 45 45 45
=========================================================================================================
Month: Jun
Counter Name 06/05 06:00 06/05 05:00 06/05 04:00 06/05 03:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS. : 45 45 45 45
SYS.SYS.SYS.SYS.SYS.SYS. : 45 45 45 45
=========================================================================================================
Month: Jun
Counter Name 06/04 18:00 06/04 17:00 06/04 16:00 06/04 15:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS. : 45 45 45 45
SYS.SYS.SYS.SYS.SYS.SYS. : 45 45 45 45
=========================================================================================================
解释
- 一口气输入: -0777选择珀尔使之成为可能。
- 沿着破折号分割整个文件(现在被视为一个长字符串):/^=+$/米意味着给定行只包含重复的等于的地方就是我们分割文件的地方。
- -A选项将使珀尔将分割后的部分填充到数组中@F。
- -nPerl 的选项将在读取下一条记录之前禁用自动打印,并且还会执行awk-类似于从输入读取的记录上的循环。
- 首先,我们存储输入中的虚线。
- 请注意,拆分操作将使第一个和最后一个元素为空,因此我们从@F在执行主要任务之前先进行数组。
- 我们设置了一个 while 循环,它消耗 2 个元素(拼接)在某个时间从@Farray.First 是标题,第二个是部分。只要数组中至少还有 2 个元素,循环就会继续。
- 关键点是决定跳过或不跳过处理标题/部分二重奏。当该部分仅包含空行或仅包含水平空白的行时,就会决定这一点(\H)。正则表达式是/^(?:\h*\n)+$/
- 现在,如果该部分不为空,则仍然需要将标题/部分二重奏与破折号缝合在一起。我们记住,在最后一个标题/部分组合在一起时,我们需要添加破折号以进行四舍五入。
答案4
与奥利夫的答案类似,也许更简单一些:
gawk -v RS='=+\n' '
NR % 2 == 0 {header = $0; next}
/[^[:space:]]/ {printf "%s", RT header RT $0}
END {print RT}
' output.txt
使用一行=
s 作为记录分隔符。标头是每个偶数记录。如果“内容”包含非空白字符,则“内容”不为空。
RT
是一个 GNU awk 特定变量,包含“与 RS 表示的文本相匹配的输入文本,即记录分隔符。每次读取记录时都会设置它。”