Awk 基于文本块中的单个值筛选文本块

Awk 基于文本块中的单个值筛选文本块,awk,sed,grep,Awk,Sed,Grep,我有一个LDIF文件,其中有大约23K个用户对象,用空行分隔。每个用户对象(文件中的文本块)都有一个workforceid值,我想删除workforceid为5个字符的任何用户对象的用户对象(整个文本块)。有两个不同公司的用户对象,一个公司有5位ID,其他公司有8位ID,我需要对8位ID的用户对象进行数据处理。数据集示例: # zhayangy, Company dn: cn=zhayangy,o=Company workforceid: 26000180 street: 699 axian R

我有一个LDIF文件,其中有大约23K个用户对象,用空行分隔。每个用户对象(文件中的文本块)都有一个workforceid值,我想删除workforceid为5个字符的任何用户对象的用户对象(整个文本块)。有两个不同公司的用户对象,一个公司有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
使用下面的命令将搜索返回所有具有workforceid的记录,但我认为只有当workforceid是第二个条目时才会返回。如果有一个命令可以找到workforceid并计算值的长度,而不管它在对象中的位置如何,那就太好了

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

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

提前谢谢

我想我在测试后得到了答案。如果我错了,请告诉我。我不确定它是否正确,但我将“workforceid”移动到了对象中的不同位置,它给出了相同的计数。所以我想我明白了

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

我很惊讶这能奏效<代码>$7似乎不是劳动力id。无论如何,我的解决方案如下:

awk -v RS='' -v ORS='\n\n' '/workforceid: [0-9]{8}/' ldif

换句话说,如果劳动力id由八位数字组成,请打印记录,否则不打印。您感兴趣的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”字段,那么您必须处理所有具有相同标记的“objectclass”字段,但这很容易处理(例如,在
val2tag[]中添加一个计数器来唯一标识每个字段)
或仅针对它们的单独数组,可能会根据它们的值进行索引,以便您可以轻松地使用中的
来测试它们的存在性),无论您希望如何处理。

请添加样本输入(例如5-10行虚构数据),该样本的预期输出-这有助于清晰性以及在建议解决方案之前的测试目的。。你还需要展示你为解决这个问题所做的努力。。既然你提到块是用空行分隔的,我建议你搜索
awk段落模式
你错了。这对你在问题中发布的示例输入不起作用,而且不必要地复杂。在您的样本中,根据您的描述,每个记录都包含workforceid,因此无需对其进行测试,并且$7是由preferredname:、Elaine或John标识的人的名字。此外,没有理由在第一个条件为真时执行的操作中将长度测试作为单独的条件,而不是首先使用复合条件,并且打印$0是默认操作。我更新了示例数据,以准确反映我拥有的数据,但使用了屏蔽数据值。我不明白为什么数据集在这种情况下很重要。任务是检查每个用户对象中由换行符分隔的workforceID,并仅保留长度为8位的文本块(整个用户对象)。此外,它还需要考虑对象中位于不同行的workforceID属性和值。也就是说,目前您看到workforceID是对象中的第二个属性,但是如果一个单独的obj在obj的末尾有workforceID会发生什么情况。我的解决方案没有像我在问题中提出的那样起作用。我更新了示例数据,以准确反映我所拥有的,但使用了隐藏的数据值。ask能够识别可能存在于用户obj中任何位置的8位workforceID。例如,示例对象在第3行显示workforceID,但是如果文件中的另一个对象在第5行显示它呢?因为我的解决方案没有将记录拆分为行或字,所以它不受影响。只有当所有记录的workforceID都在同一位置时,这才起作用。就像我的一样,但是如果你的workforceID在obj中的另一行,它就不起作用了。它对我有效。事实上,这与Ed Morton使用的解决方案几乎相同。正如我在他的解决方案下的评论中所述,他的短解决方案也不起作用,但他的长版本起作用,因此我不得不将其视为解决方案。我更新了样本数据,以准确反映我所拥有的,但使用了隐藏的数据值。ask能够识别可能存在于用户obj中任何位置的8位workforceID。例如,示例对象在第3行显示workforceID,但是如果文件中的另一个对象在第5行显示它呢?好的,我为我的答案添加了另一种方法。稳健的答案完全符合我的要求。我接受了你更有力的回答,作为我问题的答案。您提供的第二个单行程序解决方案未通过我的测试。事实上,它没有返回任何对象。