modify output of script

K

Kt Br

I've got some LDAP data I'm trying to pipe into a ruby script.

Here is an example of the data there are multiple groups (dn) in the
real data set. Sometimes the groups (dn) don't have a "seeAlso" or
"owner" associated with it:

dn: cn=test_group,ou=groups,dc=example,dc=com
owner: uid=jsmith,ou=people,dc=example,dc=com
seeAlso: uid=bwilliams,ou=people,dc=example,dc=com

Here is my script:

----------------------------------------------------------
#!/usr/bin/ruby

unless STDIN.tty?
while((line = STDIN.gets))
print $1 if /dn: cn=(.*),ou=groups,dc=example,dc=com/
print $1+'@example.com' if /owner:
uid=(.*),ou=people,dc=example,dc=com/
print $1+'@example.com' if /seeAlso:
uid=(.*),ou=people,dc=example,dc=com/
print "\n"
end
else
end
-----------------------------------------------------------

The output of my script:

test_group
(e-mail address removed)
(e-mail address removed)

What I want the output to look like:

test_group (e-mail address removed), (e-mail address removed)

Any help would be appreciated.
Thanks,
Kent
 
J

Jano Svitok

I've got some LDAP data I'm trying to pipe into a ruby script.

Here is an example of the data there are multiple groups (dn) in the
real data set. Sometimes the groups (dn) don't have a "seeAlso" or
"owner" associated with it:

dn: cn=test_group,ou=groups,dc=example,dc=com
owner: uid=jsmith,ou=people,dc=example,dc=com
seeAlso: uid=bwilliams,ou=people,dc=example,dc=com

Here is my script:

----------------------------------------------------------

Try simple state machine - either you are processing first group (then
nothing is needed), or any other (prefix with newline),
and processing the first user/address/howyoucallit (do nothing) or
later (prefix with ',')

#!/usr/bin/ruby

unless STDIN.tty?
first_group, first_user = true, true
while((line = STDIN.gets))
case line
when /dn: cn=(.*),ou=groups,dc=example,dc=com/ # it's possible to
use regexps in case statements
puts unless first_group
print $1
first_group, first_user = false, true
when /(?:eek:wner|seeAlso): uid=(.*),ou=people,dc=example,dc=com/ #
joined the two in one regexp, notice (?:) non-capturing group
print ',' unless first_user
print " #{$1}@example.com"
first_user = false
end
end
puts # final newline
end

Alternative approach would be to create a hash indexed by groups, and
values would be arrays of users.
i.e. info = Hash.new{ |h,k| h[k] = [] }
then when dn: group = $1
otherwise: info[group] << $1
When finished, just iterate over keys and values

puts info.map {|k,v| "#{k} #{v.join(', ')"}.join("\n")

Note that this approach will reorder the groups.
 
R

Robert Klemme

Try simple state machine - either you are processing first group (then
nothing is needed), or any other (prefix with newline),
and processing the first user/address/howyoucallit (do nothing) or
later (prefix with ',')

#!/usr/bin/ruby

unless STDIN.tty?
first_group, first_user = true, true
while((line = STDIN.gets))
case line
when /dn: cn=(.*),ou=groups,dc=example,dc=com/ # it's possible to
use regexps in case statements
puts unless first_group
print $1
first_group, first_user = false, true
when /(?:eek:wner|seeAlso): uid=(.*),ou=people,dc=example,dc=com/ #
joined the two in one regexp, notice (?:) non-capturing group
print ',' unless first_user
print " #{$1}@example.com"
first_user = false
end
end
puts # final newline
end

You can also encapsulate the state in the fields that have been set already:

#!/bin/env ruby

group = nil
users = []

# replace DATA with ARGF or STDIN
DATA.each do |line|
case line
when /^dn:\s+cn=([^,]*)/
print group, ' ', users.join(', '), "\n" if group
group = $1
users.clear
when /^(?:eek:wner|seeAlso):\s+uid=([^,]*)/
users << $1
end
end
print group, ' ', users.join(', '), "\n" if group

__END__
dn: cn=test_group,ou=groups,dc=example,dc=com
owner: uid=jsmith,ou=people,dc=example,dc=com
seeAlso: uid=bwilliams,ou=people,dc=example,dc=com

Alternative approach would be to create a hash indexed by groups, and
values would be arrays of users.
i.e. info = Hash.new{ |h,k| h[k] = [] }
then when dn: group = $1
otherwise: info[group] << $1
When finished, just iterate over keys and values

puts info.map {|k,v| "#{k} #{v.join(', ')"}.join("\n")

Note that this approach will reorder the groups.

Alternatively nested Arrays can be used to prevent reordering.

If the input is large then the state based approach is likely more
efficient since not the whole file content needs to stay in memory.

Kind regards

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,817
Latest member
AdalbertoT

Latest Threads

Top