通过在可靠的分隔符上增加计数器来解析多行“记录”(将/^$/
与sed一起使用。
解析如下所示的ldif(但我希望它能与其他记录类型(例如creationTime)快速通用化
dn: uid=asd,ou=People,dc=MY,dc=ORG
objectClass: ...
cn: Adam Saddler
uid: asd
creationTime: 20110409131545-0700
uidNumber: 1234
dn: uid=mfwth,ou=People,dc=MY,dc=ORG
objectClass: ...
cn: Mike Foksworth
uid: mfwth
creationTime: 20160704144535-0800
uidNumber: 12345
并希望能够生成
uid, cn, ...
asd, Adam Saddler, ...
mfwth, Mike Foksworth, ...
我想让...
解析awk
的其他字段,而不是混入gsub
s。
我正在用
进行解析$ awk
-vOFS=';'
/dn/{ i++ }
/cn/{ users[i]["cn"]=$0 }
/uid/{ users[i]["uid"]=$0 }
END{ for (j in users) print users[j]["uid"] "_" users[j]["cn"] }'
并获取(_
是'_',制表符或空格)
uid: asd_cn: Adam Saddler
uid: mfwth_cn: Mike Foksworth
相反,在存储/xx/ { $1="" ; ... }
之前修改匹配项
$ awk
-vOFS=';'
/dn/{ i++ }
/cn/{ $1="" ; users[i]["cn"]=$0 }
/uid/{ $1="" ; users[i]["uid"]=$0 }
END{ for (j in users) print users[j]["uid"] " " users[j]["cn"] }'
似乎使输出字段分隔符(OFS)再次相关?
;asd; Adam;Saddler
;mfwth; Mike;Foksworth
为什么awk将第一个作为一个块(字符串?)输出,而将第二个作为一组记录进行解析并输出?
答案 0 :(得分:1)
分配给任何字段(例如,第二个脚本中的$1=""
)明确要求awk重新编译当前记录($0
),并用FS
替换每个OFS
。 / p>
这是如何真正做您想做的事情:
$ cat tst.awk
NF {
tag = val = $0
sub(/:.*/,"",tag)
sub(/[^:]*:[[:space:]]*/,"",val)
tag2val[tag] = val
next
}
{ prt() }
END { prt() }
function prt( tagNr,tags,numTags,tag,val) {
OFS=", "
numTags = split("uid cn",tags)
if ( ++numRecs == 1 ) {
for (tagNr=1; tagNr<=numTags; tagNr++) {
tag = tags[tagNr]
printf "%s%s", tag, (tagNr<numTags ? OFS : ORS)
}
}
for (tagNr=1; tagNr<=numTags; tagNr++) {
tag = tags[tagNr]
val = tag2val[tag]
printf "%s%s", val, (tagNr<numTags ? OFS : ORS)
}
delete tag2val
}
$ awk -f tst.awk file
uid, cn
asd, Adam Saddler
mfwth, Mike Foksworth
请注意,以上代码不需要GNU awk,不需要将整个文件存储在内存中,不需要您在多个位置提供明确的标签名称,只需在{{ 1}}。实际上,如果您只是想将所有字段都以CSV格式打印,并且不想为输出重新排序,并且它们都出现在每条记录中,例如您的示例输入中,那么您就无需提及它们完全没有这是从带有冒号分隔标记的空白行分隔记录文件中生成有效CSV(例如可以读入Excel)的方法:值类似于问题中显示的值:
split("uid cn",tags)
答案 1 :(得分:0)
如果我的理解正确,您想提取=
或:
字符之后的字段。
此GNU awk脚本可能会帮助您:
awk 'BEGIN{
RS="\n\ndn: |,|\n"
FS="[=:] *"
}
NF{a=a (a?",":"")$2}
RT~/dn:/{print a;a=""}
END{print a}' file
设置记录分隔符RS
使其捕获由dn:
或,
或换行符分隔的记录。
字段分隔符设置为使用:
或=
拆分关键字和值。
main语句用所有值填充变量a
。找到dn:
关键字时或在文件末尾时,将打印变量a
。