If first pattern is found, look for second pattern. If second pattern not found, delete line

I had a spot of trouble coming up with a title, hopefully you'll understand once you read my problem... :slight_smile:

I have the output of an ldapsearch that looks like this:

dn: cn=sam,ou=company,o=com
uidNumber: 7174
gidNumber: 49563
homeDirectory: /home/sam
loginshell: /bin/bash
uid: sam
fullName: Sam Goober
sn: Goober
objectclass: itUser
objectclass: inetOrgPerson
objectclass: itAuxAudit
objectclass: organizationalPerson
objectclass: Person
objectclass: ndsLoginProperties
objectclass: Top
objectclass: posixAccount
objectclass: shadowAccount
groupMembership: cn=UPWDL,ou=WDL,o=APPS
groupMembership: cn=CAD_UP,ou=CAD,o=APPS
groupMembership: cn=EQM_Manager,ou=EQM,o=APPS
groupMembership: cn=VPN_Default_Access,ou=VPN,o=APPS
groupMembership: cn=SQD_ProxyUsers,ou=SQD,o=APPS
groupMembership: cn=FMA_Admin,ou=FMA,o=APPS
groupMembership: cn=diwvgrp026,ou=IWV,o=APPS
cn: sam

What I'm trying to do is retain everything you see in the ldapsearch output except :

groupMembership: cn=UPWDL,ou=WDL,o=APPS
groupMembership: cn=CAD_UP,ou=CAD,o=APPS
groupMembership: cn=EQM_Manager,ou=EQM,o=APPS
groupMembership: cn=VPN_Default_Access,ou=VPN,o=APPS
groupMembership: cn=SQD_ProxyUsers,ou=SQD,o=APPS
groupMembership: cn=FMA_Admin,ou=FMA,o=APPS

In other words, I want to get rid of all lines that start with "groupMembership:cn=" unless they have a group name that starts with cn=diwvgrp* The groupMembership values returned by the ldapsearch on each user (there are about 200 users) may have one groupMembership that starts with cn=diwvgrp, or they may have several.

groupMembership: cn=diwvgrp026,ou=IWV,o=APPS
groupMembership: cn=diwvgrp027,ou=IWV,o=APPS
groupMembership: cn=diwvgrp052,ou=IWV,o=APPS
groupMembership: cn=diwvgrp086,ou=IWV,o=APPS

I always want to keep the groups that contain the line "diwvgrp" and always want to discard any other line that begins with "groupMembership but doesn't contain diwvgrpXXX (where XXX is a number between 000 and 999).

I also have to keep ALL the other lines that ldapsearch has returned. So using the above example, I need to turn it from what I posted above, into this:

dn: cn=sam,ou=company,o=com
uidNumber: 7174
gidNumber: 49563
homeDirectory: /home/sam
loginshell: /bin/bash
uid: sam
fullName: Sam Goober
sn: Goober
objectclass: itUser
objectclass: inetOrgPerson
objectclass: itAuxAudit
objectclass: organizationalPerson
objectclass: Person
objectclass: ndsLoginProperties
objectclass: Top
objectclass: posixAccount
objectclass: shadowAccount
groupMembership: cn=diwvgrp026,ou=IWV,o=APPS
cn: sam

I'd prefer to use bash scripting to do this, if possible. There is a list of names that the ldapsearch goes through, returning the above information for each of the 200 or so users. The command line I use to generate the file (slightly obfuscated) is:

ldapsearch -h superserver.company.com -p 389 -b "ou=company,o=organization" -L -f ./iwvnusers-test.txt "(cn=%s)" cn sn fullName Language passwordAllowChange uid uidNumber homeDirectory gidNumber loginshell objectclass groupMembership

Once I run that ldapsearch, I end up with a file with about 200 entries in it, each one of which looks similar to the example at the beginning of this post.

I've tried using grep -o and storing the output into a variable, deleting all the lines starting with "groupMembership" then taking what's in the variable and inserting it back into the text, but that's not working. It (along with a couple of other ways) I've found that will work with the output from a single user, but when run against a list of users, it doesn't replace the strings in the correct place.

If anyone has any thoughts on this, I would be most-grateful. If PERL is the only answer, I can deal with that, but would prefer to use Bash if it's not too unrealistic.

Thank you,
Sam

In a variety of tools from sed on up, your strategy must be to capture the lines starting with the header in a buffer until you find a next header or EOF, then if the first header is not to your liking, delete all but the second header line and return to get another line. In sed. this is /pattern/ match, b and : for loop, N to add another line to the buffer, $ to test EOF. The last group is irregular as it has no second header line. You might h the line, remove the second header if any, decide if it is a keeper, and the g the original buffer back. You might add a dummy final header to stdin using "( cat file ; echo dummy )|sed", but of course you need to remove it. You can d or "s/...//" what you dislike or "sed -n" and p what you like, but remember there is a second header in the buffer!

pipe your ldapsearch to

awk '$1!~/^groupMembership:$/ || $2~/^cn=diwvgrp/'

Also possible with sed

sed '/^groupMembership:/{/cn=diwvgrp/!d;}'
1 Like