# Modify output of script

**URL:** <https://www.ruby-forum.com/t/modify-output-of-script/137515>\
**Category:** Ruby\
**Created:** [May 13, 2008, 10:28pm UTC](https://www.ruby-forum.com/t/modify-output-of-script/137515 "2008-05-13T22:28:44Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![kentbarber](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/e68b1a/32.png) [@kentbarber](https://www.ruby-forum.com/u/kentbarber)\
**Post date:** [May 13, 2008, 10:28pm UTC](https://www.ruby-forum.com/t/modify-output-of-script/137515/1 "2008-05-13T22:28:44Z")

</div>

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  
removed\_email\_address@domain.invalid  
removed\_email\_address@domain.invalid

What I want the output to look like:

test\_group removed\_email\_address@domain.invalid, removed\_email\_address@domain.invalid

Any help would be appreciated.  
Thanks,  
Kent

---

<div class="post-metadata">

**Author:** ![kentbarber](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/e68b1a/32.png) [@kentbarber](https://www.ruby-forum.com/u/kentbarber)\
**Post date:** [May 13, 2008, 11:19pm UTC](https://www.ruby-forum.com/t/modify-output-of-script/137515/2 "2008-05-13T23:19:20Z")

</div>

On Tue, May 13, 2008 at 10:28 PM, Kt Br wrote:

> 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 /(?:owner|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.

---

<div class="post-metadata">

**Author:** ![kentbarber](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/e68b1a/32.png) [@kentbarber](https://www.ruby-forum.com/u/kentbarber)\
**Post date:** [May 13, 2008, 11:51pm UTC](https://www.ruby-forum.com/t/modify-output-of-script/137515/3 "2008-05-13T23:51:15Z")

</div>

On 13.05.2008 23:18, Jano S. wrote:

> > 
> 
> 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 /^(?:owner|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
