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
的实用组合,概念上相对简单:

LinuxBSD/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