脚本/过滤器多行&多字段记录,行数可变

时间:2014-08-07 08:05:32

标签: awk multiple-columns

tldr; SAN CLI命令发出可怕的格式,使自动化变得困难。 此格式已修复。

我的问题: 我试图编写有关SAN快照的内联和脱机的脚本, 但是SAN CLI将文本包装在不方便的地方。

解决方案所需的输出(每条记录)是两个字段, 快照和状态,在一行:

VolumeName-YYYY-MM-DD-HH:MM:SS.NNNN.N online/offline
VolumeName-YYYY-MM-DD-HH:MM:SS.NNNN.N online/offline

注意: VolumeName可以包含1到64个字符 记录有2-4行 计划也可以命名,最多64个字符 这将导致记录为8行。

实施例

1. Real world
SAN-01> volume select hv01-200G show snapshots
Name                        Permission Status      Schedule Connections
--------------------------- ---------- ----------- -------- -----------
hv01-200G-2013-11-29-12:33: read-write offline              0
  54.1798.1
hv01-200G-2014-08-05-11:00: read-write offline     Site01 H 0
  00.9698.1                                          V Hour
                                                     ly

2. Longest possible volume name
SAN-01> volume select 123456789012345678901234567890123456789012345678901234
567890123 show snapshots
Name                        Permission Status      Schedule Connections
--------------------------- ---------- ----------- -------- -----------
123456789012345678901234567 read-write offline              0
  8901234567890123456789012
  34567890123-2014-08-07-13
  :05:09.9761.1
123456789012345678901234567 read-write online               0
  8901234567890123456789012
  34567890123-2014-08-07-13
  :05:23.9762.1


3. Shortest volume name
SAN-01> volume select X show snapshots
Name                        Permission Status      Schedule Connections
--------------------------- ---------- ----------- -------- -----------
X-2014-08-07-13:10:35.9764. read-write offline              0
  1
X-2014-08-07-13:10:46.9765. read-write online               0

1

任何人都可以帮助一个合理的解决方案 - grep sed awk perl或 我可以在linux机器上运行其他任何东西吗?

干杯, 杰森

1 个答案:

答案 0 :(得分:1)

这个awk可以解决问题:

awk '/(on|off)line/ { o[++c]=$3 } substr($0,0,27)~$1 { v[c]=v[c] $1 } END{ for(i=1;i<=c;++i) print v[i],o[i] }' file

<强>解释

当单词on / offline匹配时,递增计数器c,然后创建状态并将其保存到数组o。只要第一列中存在某些内容(即该行上的第一个字段与该行中的前27个字符匹配),就添加到卷数据信息中。处理完文件后,打印出两个数组的相应项目。

测试

真实:

$ awk '/(on|off)line/ { o[++c]=$3 } substr($0,0,27)~$1 { v[c]=v[c] $1 } END{ for(i=1;i<=c;++i) print v[i],o[i] }' real    
hv01-200G-2013-11-29-12:33:54.1798.1 offline
hv01-200G-2014-08-05-11:00:00.9698.1 offline

最长:

$ awk '/(on|off)line/ { o[++c]=$3 } substr($0,0,27)~$1 { v[c]=v[c] $1 } END{ for(i=1;i<=c;++i) print v[i],o[i] }' longest 
123456789012345678901234567890123456789012345678901234567890123-2014-08-07-13:05:09.9761.1 offline
123456789012345678901234567890123456789012345678901234567890123-2014-08-07-13:05:23.9762.1 online

最短:

$ awk '/(on|off)line/ { o[++c]=$3 } substr($0,0,27)~$1 { v[c]=v[c] $1 } END{ for(i=1;i<=c;++i) print v[i],o[i] }' shortest 
X-2014-08-07-13:10:35.9764.1 offline
X-2014-08-07-13:10:46.9765.1 online

顺便说一句,你提到你在使用mawk这个脚本时遇到了一些麻烦。我相信其原因在于开头的正则表达式。 mawk不会假设扩展的正则表达式,所以你必须做一些调整:

$ mawk '/\(on\|off\)line/ { o[++c]=$3 } substr($0,0,27)~$1 { v[c]=v[c] $1 } END{ for(i=1;i<=c;++i) print v[i],o[i] }' real

应该有效。请注意,我可能错了,因为我没有mawk测试,但我确实使用grep观察到这种行为:

$ grep '(on|off)line' real                             # doesn't work
$ grep -E '(on|off)line' real                          # works (extended regexp)
hv01-200G-2013-11-29-12:33: read-write offline              0
hv01-200G-2014-08-05-11:00: read-write offline     Site01 H 0
$ grep '\(on\|off\)line' real                          # also works
hv01-200G-2013-11-29-12:33: read-write offline              0
hv01-200G-2014-08-05-11:00: read-write offline     Site01 H 0