dougmilbourne has asked for the wisdom of the Perl Monks concerning the following question:

Hello All, Is there a way to search and replace a string, where part of the string is unknown. Example input:
NAME010 DESC025 DATE009 NAME011 DESC035 DATE009 ...
Now the output:
NAME DESCRIPTION DATE NAME DESCRIPTION DATE
If one knows that the field is always going to be a certain length, prefixed by a specific id ... can the variabe nature of the last couple of chars be handled using a wild card? Thanks in advance

Replies are listed 'Best First'.
Re: Search and replace with a wild card
by ikegami (Patriarch) on Aug 24, 2004 at 18:29 UTC

    Since you're dealing with fixed length fields, substr works well:

    $field_start = 8; # 0-based $field_length = 8; # Get current value: $old_value = substr($s, $field_start, $field_length); $old_value =~ s/\s+$//; # Change the value: $new_value = 'bla'; substr($s, $field_start, $field_length) = substr($new_value . (' 'x$field_length), 0, $field_length);

    And if you're converting from fields of one size to fields of another size:

    foreach (@old_records) { my $name = substr($_, 0, 8); $name =~ s/\s+$//; my $desc = substr($_, 8, 8); $desc =~ s/\s+$//; my $date = substr($_, 16, 8); $date =~ s/\s+$//; $name = ...reformat name...; $desc = ...reformat desc...; $date = ...reformat date...; push(@new_records, sprintf("%-7s %-13s %s\n", $name, $desc, $date) ); }
Re: Search and replace with a wild card
by tachyon (Chancellor) on Aug 24, 2004 at 16:57 UTC

    Well you have totally got me on the logic! Why not just print "NAME DESCRIPTION DATE\n" for 1..$n; anyway to convert what you have to what you say you want:

    while(<DATA>){ s{(NAME)\d*\s*(DESC)\d*\s*(DATE)\d*\s*} {$1 ${2}RIPTION $3\n}g; print; } __DATA__ NAME010 DESC025 DATE009 NAME011 DESC035 DATE009

    In general there is nothing that perl *can't do* when it comes to munging text.

    cheers

    tachyon

Re: Search and replace with a wild card
by jbware (Chaplain) on Aug 24, 2004 at 17:04 UTC
    Like the others, I was a bit confused by the exact request. But here is another solution that returns the #s, which I'm wondering is what you want.
    my %xref; $xref{'NAME'} = 'NAME'; $xref{'DESC'} = 'DECSRIPTION'; $xref{'DATE'} = 'DATE'; while (<DATA>) { # s/(NAME|DESC|DATE)(\d*)/$xref{$1}/eg; s/(NAME|DESC|DATE)(\d*)/$2/g; print; } __DATA__ NAME010 DESC025 DATE009 NAME011 DESC035 DATE009


    -jbWare
Re: Search and replace with a wild card
by borisz (Canon) on Aug 24, 2004 at 16:59 UTC
    untested:
    s/NAME\d{3}\sDESC\d{3}\sDATE\d{3}/NAME DESCRIPTION DATE/g;
    Boris
      Thanks that was the trick ... sorry about the confusing description I was trying to come up with example, but wasn't quite sure how to phrase it.
Re: Search and replace with a wild card
by tachyon (Chancellor) on Aug 25, 2004 at 00:37 UTC

    If your data is fixed width then unpack can be quite handy to chop out the data.

    while(<DATA>) { @bits = unpack "A4A4 A4A4 A4A4", $_; print "[$_] '$bits[$_]' " for 0..$#bits; print $/; } __DATA__ NAME010 DESC025 DATE009 NAME011 DESC035 DATE009

    cheers

    tachyon