bashshell脚本:根据字段分隔符计算文件中每个段落的行数?
我想分析日志文件,但在这种情况下卡住了: 例如: 我有一个格式如下的文件:bashshell脚本:根据字段分隔符计算文件中每个段落的行数?,bash,shell,awk,Bash,Shell,Awk,我想分析日志文件,但在这种情况下卡住了: 例如: 我有一个格式如下的文件: 140508 0:00:19 10 abc def 9 djdj djdjd 12 fjfj fjfjj 140508 0:00:24 10 dhdh dhdh 19 dddh hdhdhd 1838 jcjj ddhfhfh 17
140508 0:00:19 10 abc def
9 djdj djdjd
12 fjfj fjfjj
140508 0:00:24 10 dhdh dhdh
19 dddh hdhdhd
1838 jcjj ddhfhfh
17 fhfhh fhfhfh
140508 0:00:29 10 ababa cbcbc
字段分隔符为140508(年月日)
我想根据字段分隔符输出每个段落中的行数:
140508 0:00:19 3
140508 0:00:24 4
140508 0:00:29 1
谢谢。使用awk:
awk '/^[0-9]{6} /{if (c) print a, b, c; a=$1; b=$2; c=1; next} {c++} END{print a, b, c}' file
140508 0:00:19 3
140508 0:00:24 4
140508 0:00:29 1
使用awk:
awk '/^[0-9]{6} /{if (c) print a, b, c; a=$1; b=$2; c=1; next} {c++} END{print a, b, c}' file
140508 0:00:19 3
140508 0:00:24 4
140508 0:00:29 1
使用awk
awk '/:/{h=$1 FS $2}{a[h]++}END{for (i in a) print i,a[i]}' file
解释
,仅在/:/{h=$1fs$2}
行上工作,并生成数组a的索引:
对该索引上的时间求和{a[h]+}
遍历数组a并执行打印作业{对于(a中的i)print i,a[i]}
awk '/:/{h=$1 FS $2}{a[h]++}END{for (i in a) print i,a[i]}' file
解释
,仅在/:/{h=$1fs$2}
行上工作,并生成数组a的索引:
对该索引上的时间求和{a[h]+}
遍历数组a并执行打印作业{对于(a中的i)print i,a[i]}
- 使用GNU
awk
:
awk --re-interval -v RS='(^|\n)[0-9]{6} ' \
'$0=="" {sep=RT; next} {print sep $1, 1+gsub("\n.",""); sep=substr(RT,2)}' file
注意:如果您的gawk
版本为>=4.0
,则不需要--re interval
选项
说明:
- 日期表达式
用作记录分隔符([0-9]{6}
),它自动将输入拆分为所需的段落;在前面加上RS
可确保仅在行的开头执行匹配(^ |\n)
包含与手头记录的RT
regex匹配的文字记录终止符;它保存在RS
变量中,用于处理下一条记录。sep
- 请注意,由于输入以记录分隔符开头,因此报告的第一条记录为空-因此出现了
模式和相关操作$0==“”
- 对于所有后续记录,必须将inital
切掉分隔符,这是\n
调用所做的substr()
- 请注意,由于输入以记录分隔符开头,因此报告的第一条记录为空-因此出现了
是一个小技巧,它可以有效地简单地计算记录中非空行的数量(1+gsub(“\n.,”)
返回替换的数量)gsub()
- 使用GNU
awk
:
awk --re-interval -v RS='(^|\n)[0-9]{6} ' \
'$0=="" {sep=RT; next} {print sep $1, 1+gsub("\n.",""); sep=substr(RT,2)}' file
注意:如果您的gawk
版本为>=4.0
,则不需要--re interval
选项
说明:
- 日期表达式
用作记录分隔符([0-9]{6}
),它自动将输入拆分为所需的段落;在前面加上RS
可确保仅在行的开头执行匹配(^ |\n)
包含与手头记录的RT
regex匹配的文字记录终止符;它保存在RS
变量中,用于处理下一条记录。sep
- 请注意,由于输入以记录分隔符开头,因此报告的第一条记录为空-因此出现了
模式和相关操作$0==“”
- 对于所有后续记录,必须将inital
切掉分隔符,这是\n
调用所做的substr()
- 请注意,由于输入以记录分隔符开头,因此报告的第一条记录为空-因此出现了
是一个小技巧,它可以有效地简单地计算记录中非空行的数量(1+gsub(“\n.,”)
返回替换的数量)gsub()
这似乎是错的。我使用上面的示例运行您的脚本,结果显示:“140508 0:00:29 8”我还提供了awk命令的输出。这和你预期的输出不一样吗?你能在脚本中解释一下(c)吗。是的,你的结果是正确的,但当我运行它时,会给我另一个结果。[root@TESTSRV用户]#cat测试140508 0:00:19 10 abc def 9 djdj DJD 12 fjfj FJFJJ140508 0:00:24 10 DHDHDH 19 DDDHHDHD 1838 jcjj DDHFH 17 FHFHFHFHFH140508 0:00:29 10 ababa CBC[root@TESTSRV用户]#awk'/[0-9]{6}/{如果(c)打印$1,$2,c;c=1;下一个}{c++}END{print$1,$2,c}test 140508 0:00:29 8
c
只是一个计数器,每次匹配模式时,它都以1
开头。如果您遇到问题,请在您的问题中提供一个可以重现问题的示例输入,我将相应地调整我的命令+1.您的解决方案甚至与POSIX兼容。(在GNUawk
<4上,您必须添加--posix
或--re interval
使其工作。)锚定正则表达式并添加空格将有助于健壮性-/^[0-9]{6}/
。这似乎是错误的。我使用上面的示例运行您的脚本,结果显示:“140508 0:00:29 8”我还提供了awk命令的输出。这和你预期的输出不一样吗?你能在脚本中解释一下(c)吗。是的,你的结果是正确的,但当我运行它时,会给我另一个结果。[root@TESTSRV用户]#cat测试140508 0:00:19 10 abc def 9 djdj DJD 12 fjfj FJFJJ140508 0:00:24 10 DHDHDH 19 DDDHHDHD 1838 jcjj DDHFH 17 FHFHFHFHFH140508 0:00:29 10 ababa CBC[root@TESTSRV用户]#awk'/[0-9]{6}/{如果(c)打印$1,$2,c;c=1;下一个}{c++}END{print$1,$2,c}test 140508 0:00:29 8c
只是一个计数器,每次匹配模式时,它都以1
开头。如果您遇到问题,请在您的问题中提供一个可以重现问题的示例输入,我将相应地调整我的命令+1.您的解决方案甚至与POSIX兼容。(在GNUawk
<4上,您必须添加--posix
或--re interval
以使其工作。)锚定正则表达式并附加空格将有助于健壮性-/^[0-9]{6}/
。这对我来说很有用。你能解释一下你的剧本吗??谢谢。它很简洁,但请注意,由于在中使用了i,因此输出行的顺序与输入顺序不匹配。此外,与/^[0-9]匹配