From owner-freebsd-questions@FreeBSD.ORG Sun Apr 15 05:58:18 2007 Return-Path: X-Original-To: freebsd-questions@freebsd.org Delivered-To: freebsd-questions@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 1AE1E16A400 for ; Sun, 15 Apr 2007 05:58:18 +0000 (UTC) (envelope-from parv@pair.com) Received: from mta16.adelphia.net (mta16.mail.adelphia.net [68.168.78.211]) by mx1.freebsd.org (Postfix) with ESMTP id B61CF13C44C for ; Sun, 15 Apr 2007 05:58:17 +0000 (UTC) (envelope-from parv@pair.com) Received: from default.chvlva.adelphia.net ([24.126.17.68]) by mta16.adelphia.net (InterMail vM.6.01.05.04 201-2131-123-105-20051025) with ESMTP id <20070415055816.OAUQ26916.mta16.adelphia.net@default.chvlva.adelphia.net> for ; Sun, 15 Apr 2007 01:58:16 -0400 Received: by default.chvlva.adelphia.net (Postfix, from userid 1000) id 24D01B545; Sun, 15 Apr 2007 01:58:33 -0400 (EDT) Date: Sun, 15 Apr 2007 01:58:33 -0400 From: Parv To: f-q Message-ID: <20070415055833.GA7730@holestein.holy.cow> Mail-Followup-To: f-q MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Subject: Re: [OT] can sed handle this situation? (might require variable) X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 15 Apr 2007 05:58:18 -0000 Darn, forgot to copy to the dear list; so here it is (sent to OP previously) ... in message <1176603461.20274.12.camel@joe.realss.com>, wrote Zhang Weiwu thusly... > > Dear list. I could not find a mailing list about 'sed' (there is > an very inactive Yahoo Group though) so I wish to try some luck > here. Try, comp.unix.misc newsgroup. > I've got a situation that looks like require using variable and > not possible to process with sed. But I am not sure. Can someone > suggest me if this task is out of scope of sed? Try some variation of what Garret suggested if sed is the requirement and skip rest of the message. > The input document is sections of data separated by an empty new > line ... > dn: uid=ABB,ou=contacts,ou=china,dc=ahk,dc=de > uid: ABB > ahkCreateTimeStamp: 19960328000000Z > creatorsName: cn=manager,dc=ahk,dc=de > createTimestamp: 20060425094550Z > > dn: uid=paulblome,ou=contacts,ou=china,dc=ahk,dc=de > uid: paulblome > sn: Blome > createTimestamp: 20060417071950Z > modifiersName: cn=manager,dc=ahk,dc=de > modifyTimestamp: 20060630094026Z > > The above sample showed two sections in input data. It's required to > process the data in following rule: > > if a data section has "ahkCreateTimeStamp: abc", replace it > with "createTimestamp: abc" and remove the original > "createTimestamp: def" line; > > That is, the result data of above sample should be: > > dn: uid=ABB,ou=contacts,ou=china,dc=ahk,dc=de > uid: ABB > createTimestamp: 19960328000000Z > creatorsName: cn=manager,dc=ahk,dc=de > > dn: uid=paulblome,ou=contacts,ou=china,dc=ahk,dc=de > uid: paulblome > sn: Blome > createTimestamp: 20060417071950Z > modifiersName: cn=manager,dc=ahk,dc=de > modifyTimestamp: 20060630094026Z Here is my version in Perl (v5.8.8; run it by giving it files to process as command line arguments; no files are modified; output goes to the standard output) ... #!/usr/local/bin/perl use warnings; use strict; my $orig = 'createTimestamp'; my $changed = 'ahkCreateTimeStamp' ; # Mapping of changed & original strings with related regular # expressions. my %replacement; @replacement{ ( 'changed' , 'orig' ) } = map { [ $_ , qr(^ \s* # Optional whitespace at the beginning; $_ # time stamp text; \s* : # optional whitespace before colon; \s* # optional whitespace; \S+ # non whitespace character sequence (time stamp); .* $ # then anything or nothing else at the end. )xm ] } ( $changed , $orig ) ; # Process files, given as command line arguments. Output is # printed on standard output, no file is actually modified. for my $file ( @ARGV ) { my $fh; unless ( open $fh , '<' , $file ) { warn "Cannot open file '$file': $!\n" ; next; } update_time_stamp( \%replacement , $fh ); close $fh or die "Cannot close '$file': $!\n" ; } exit; sub update_time_stamp { my ( $map , $fh ) = @_; my $changed = $map->{'changed'}; my $orig = $map->{'orig'}; # Set input record separator to parse data in blocks. local $/ = "" ; while ( my $block = <$fh> ) { # Nothing to do if there is no ahk* string. next unless $block =~ m/$changed->[1]/ && $block =~ m/$orig->[1]/ ; for ( $block ) { # Remove original replacement time stamp line. (Order does # not matter as only the text is changed not the associated # time stamp value.) s/$orig->[1]//; # Update time stamp string. s/$changed->[0]/$orig->[0]/; } # Remake the block by removing empty line (caused by removal of # replacement time stamp line.) $block = join "\n" , grep { $_ !~ m/^\s*$/ } split /\n+/ , $block ; # Add removed new line at the end, and another as separator. $block .= "\n\n" ; } # For each & every block processed ... continue { print $block ; } } __END__ - Parv --