首页 > 解决方案 > 根据文本块中的单个值过滤文本块

问题描述

我有一个 LDIF 文件,其中包含大约 23K 的用户对象,由空行分隔。每个用户对象(文件中的文本块)都有一个 workerid 值,我想删除任何具有 5 个字符的 workerid 的用户对象的用户对象(整个文本块)。有来自两家不同公司的用户对象,一家公司有 5 位 ID,其他公司有 8 位 ID,我需要对具有 8 位 ID 的用户对象进行数据处理。数据集示例:

# zhayangy, Company
dn: cn=zhayangy,o=Company
workforceid: 26000180
street: 699 axian Road
st: Shanghai
preferredname: Zhao, Yangyang
physicaldeliveryofficename: ABC01:
ou: IT Engineering
mail: yangyang.zhao@sample.com
givenname: Yangyang
fullname: Yangyang Zhao
employeetype: Cont
employeestatus: Active
costcenter: ABCD501641
companycategory: abc.com
co: China
city: Shanghai
uid: zhayangy
sn: Zhao
cn: zhayangy
objectclass: inetOrgPerson
objectclass: ApplicationAttrs
objectclass: organizationalPerson
objectclass: Person
objectclass: LoginProperties
objectclass: Top
objectclass: PasswordUser
objectclass: UserAux
objectclass: FolderUser
objectclass: eSystem
objectclass: pwUser
objectclass: AuthAttrs

# mikhaylo, Company
dn: cn=mikhaylo,o=Company
workforceid: 76000838
street: Gradskoe shoe, 11A block 1
preferredname: Mikhaylov, Vladislav
postalcode: 12345
physicaldeliveryofficename: ABW02:
ou: Presales ABCE
mail: vladislav.mikhaylov@sample.com
givenname: Vladislav
fullname: Vladislav Mikhaylov
employeetype: Employee
employeestatus: Active
costcenter: ABCA500189
companycategory: abc.com
co: Russian Federation
city: Moscow
uid: mikhaylo
sn: Mikhaylov
cn: mikhaylo
objectclass: inetOrgPerson
objectclass: ApplicationAttrs
objectclass: organizationalPerson
objectclass: Person
objectclass: LoginProperties
objectclass: Top
objectclass: PasswordUser
objectclass: UserAux
objectclass: FolderUser
objectclass: eSystem
objectclass: pwUser
objectclass: AuthAttrs

使用下面的命令将搜索返回所有具有劳动力 ID 的记录,但我认为只有当劳动力 ID 是第二个条目时。如果有一个命令可以找到 workerid 并计算该值的长度,而不管它在对象中的什么位置,那就太好了。

基本上我需要一些如何添加对长度的检查,例如:if(length($2) == 5),但 $2 是文本块中的第二行,而不是劳动力 ID 行或列中的第二列。取决于你如何看待它。

awk -v RS='' '/workforceid/ {if ( length($7) == 5 ) print $0}' ORS='\n\n' fullextract.ldif

提前致谢

标签: awksedgrep

解决方案


您感兴趣的 ID 是 4 美元,而不是 2 美元或 7 美元,您只需要:

awk -v RS= -v ORS='\n\n' 'length($4) == 8' fullextract.ldif

您可以打印这些字段来查看。

如果它可以在任何地方:

awk -v RS= -v ORS='\n\n' '/(^|\n)workforceid: [0-9]{8}(\n|$)/' fullextract.ldif

解决数据对问题的更稳健、更通用的方法tag: value是创建一个存储它们的数组,然后对数组进行操作,例如:

awk '
NF {
    rec = rec $0 ORS
    tag = val = $0
    sub(/:.*/,"",tag)
    sub(/[^:]+: /,"",val)
    tag2val[tag] = val
    next
}
{ prt(); rec=""; delete tag2val }
END { prt() }
function prt() {
    if ( length(tag2val["workforceid"]) == 8 ) {
        print rec
    }
}
' file

有了它,在其他字段上添加额外的测试,只打印特定的字段等是微不足道的。对于你的特定数据,如果你想单独测试或打印它们,你必须处理所有具有相同标签的“objectclass”字段但是这很容易处理(例如,添加一个计数器来唯一标识每个val2tag[]数组或一个单独的数组,可能由它们的值索引,以便您可以轻松地in用来测试它们的存在),但是您希望它处理。


推荐阅读