From: Robert Klemme Date: 2008-05-14T06:50:05+09:00 Subject: Re: modify output of script On 13.05.2008 23:18, Jano Svitok wrote: > On Tue, May 13, 2008 at 10:28 PM, Kt Br wrote: >> 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 /(?: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 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