Awk 读到了/
我有以下几行文字:Awk 读到了/,awk,filter,Awk,Filter,我有以下几行文字: 170311 005201 0433 DE(N) itemhandling itemAddBarCodeData: Barcode(1/1) <0157357069/OK> ##[ti=7672, 170311 005323 0433 DE(N) itemhandling itemAddBarCodeData: Barcode(1/1) </NOREAD> ##[ti=7672, 任何帮助都将不胜感激 谢谢您可以使用以下脚本: script.awk
170311 005201 0433 DE(N) itemhandling itemAddBarCodeData: Barcode(1/1) <0157357069/OK> ##[ti=7672,
170311 005323 0433 DE(N) itemhandling itemAddBarCodeData: Barcode(1/1) </NOREAD> ##[ti=7672,
任何帮助都将不胜感激
谢谢您可以使用以下脚本: script.awk
/\/[A-Z]+>/ { match($1"-"$2,/(..)(..)(..)-(..)(..)(..)/,ts)
dt=mktime( sprintf("20%s %s %s %s %s %s",
ts[1], ts[2], ts[3],
ts[4], ts[5], ts[6]) )
dtd = strftime( "%d-%m-%y", dt )
dts = strftime( "%H:%M:%S", dt )
match ( $0, /\/[A-Z]+>/) # set RSTART and RLENGTH
print dtd, dts, substr( $0, RSTART+1, RLENGTH-2)
}
按如下方式运行:awk-vofs=,-f script.awk yourfile
重要的部分是第二个match
函数调用,它匹配
- 一串大写字母
[a_Z]
- 前面有一个
/
- 后跟一个
李>
OK
和NOREAD
案例,而不是条形码(1/1)
变量
和RSTART
RLENGTH
match
函数设置,我们必须按+1和-2进行更正,因为匹配项重新包含/
和
第一个
match
、mktime、strftime和sprintf
函数调用是格式化日期和时间的另一种方式。时间函数是GNU AWK扩展 这里是awk
和sed
的实用组合,概念上相对简单:
在Linux和BSD/macOS上:
awk -F'[ />]' -v OFS=, '/itemAddBarCodeData/ {print $1, $2, $10}' file |
sed -E 's/^(..)(..)(..),(..)(..)(..)/\3-\2-\1,\4:\5:\6/'
在Windows系统上,从cmd.exe
调用,不同的引用和行继续规则适用(假设存在移植的GNU实用程序):
请注意:
- 必须使用
字符串而不是“…”
字符串来保护嵌入内容不被shell解释“…”
- 与Unix上的
不同,“…”
对$
没有特殊意义,因此它可以按原样使用cmd.exe
作为行上的最后一个字符用作显式行连续字符,并且该行必须在^
之前断开(而在Unix上,以
结尾的行是隐式连续的)。
此处仅用于可读性;当然,您可以将命令放在一行上
awk -F"[ />]" '{patsplit($1, a, /[0-9]{2}/); patsplit($2, b, /[0-9]{2}/);
printf("%s-%s-%s,%s:%s:%s,%s\n",a[3],a[2],a[1],b[1],b[2],b[3],$10)}' inpufile
输出:
11-03-17,00:52:01,OK
11-03-17,00:53:23,NOREAD
-F“[/>]”
-“复合”字段分隔符
patsplit(字符串、数组[、字段pat[、步骤]])
将字符串分成由fieldpat定义的片段,并将片段存储在数组和
seps数组中的分隔符字符串
常规awk版本:
awk '
{
d=$1$2
gsub(/../,"& ",d)
split(d,T)
split($8,R,"[/>]")
printf "%s-%s-%s,%s:%s:%s,%s\n",T[3],T[2],T[1],T[4],T[5],T[6],R[2]
}
' file
在文件中包含脚本时: script.awk:
{
d=$1$2
gsub(/../,"& ",d)
split(d,T)
split($8,R,"[/>]")
printf "%s-%s-%s,%s:%s:%s,%s\n",T[3],T[2],T[1],T[4],T[5],T[6],R[2]
}
awk -f script.awk file
挤在一行上
awk '{d=$1$2; gsub(/../,"& ",d); split(d,T); split($8,R,"[/>]"); printf "%s-%s-%s,%s:%s:%s,%s\n",T[3],T[2],T[1],T[4],T[5],T[6],R[2]}' file
当您使用awk时,不需要grep。对于gensub(),使用GNU awk:
请为给定输入指定所述脚本的所需输出。所需输出的第二个字段(“00:00:01”)是否为常量字段?如果不是,它是如何从输入中计算出来的?Lars,字段(“00:00:01”)只是一个时间字段,我现在可以得到OK。Hi Lars感谢您的快速响应和回答,有没有一种方法可以在一行上实现这一点?我在批处理文件中运行了一系列其他行,因此试图保持它的结构化。嗨,拉尔斯,我创建了您的脚本,它工作得很好,如果可能的话,可以使用一行命令来避免创建单独的脚本。@Fabby我更改了答案。@Fabby当然您可以将脚本的内容作为awk的参数。为了更好的可读性,我将脚本保留在答案中。嗨,Lars,感谢脚本,尝试将此添加到一行Hi Roman,似乎无法继续,我应该说我正在windows计算机上通过DOS批处理文件运行此脚本。它将打印没有
/OK
或/NOREAD
字符串的行。请注意,文件中有/
,就像条形码(1/1)
部分一样,感谢Ed感谢您的回复,它似乎与“我必须始终使用“使用引号使gawk在Windows中工作?对于任何使用Windows的人来说,常见的建议是将您的awk脚本保存在文件中,并作为awk-f script
调用,而不是试图在命令行上指定它,以避免Windows噩梦般的引用规则。或者最好安装cygwin并从中调用awk。
awk '
{
d=$1$2
gsub(/../,"& ",d)
split(d,T)
split($8,R,"[/>]")
printf "%s-%s-%s,%s:%s:%s,%s\n",T[3],T[2],T[1],T[4],T[5],T[6],R[2]
}
' file
{
d=$1$2
gsub(/../,"& ",d)
split(d,T)
split($8,R,"[/>]")
printf "%s-%s-%s,%s:%s:%s,%s\n",T[3],T[2],T[1],T[4],T[5],T[6],R[2]
}
awk -f script.awk file
awk '{d=$1$2; gsub(/../,"& ",d); split(d,T); split($8,R,"[/>]"); printf "%s-%s-%s,%s:%s:%s,%s\n",T[3],T[2],T[1],T[4],T[5],T[6],R[2]}' file
$ awk '/itemAddBarCodeData/{print gensub(/(..)(..)(..) (..)(..)(..).*\/([^>]+).*/,"\\3-\\2-\\1,\\4:\\5:\\6,\\7",1)}' file
11-03-17,00:52:01,OK
11-03-17,00:53:23,NOREAD