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

I need some help on removing the middle chars and leave the first 5 characters and last 5 characters using regex

i want this output

0x388c ... b19297

but am getting this error Use of uninitialized value $_ in pattern match (m//)

my $char = "0x388c818ca8b9251b393131c08a736a67ccb19297"; my($output) = $char = /^(?<=\S{5})\S(?=\S{7})/; print $output;

Replies are listed 'Best First'.
Re: remove chars with regex
by ikegami (Patriarch) on Feb 26, 2025 at 14:15 UTC

    The error come from using = when you meant to use =~.

    But the pattern is also wrong. There will never be 5 non-space characters before the first character of the string, for starters.

    Fixed:

    my ( $output ) = $char =~ /(?<=^\S{5})(\S+)(?=\S{5}\z)/;

    There's really no point in using look-arounds or \S, though.

    my ( $output ) = $char =~ /^.{5}(.*).{5}\z/s;

    Faster and cleaner:

    my $output = substr( $char, 5, -5 );
      I think that would return the middle part but not result in "(5 chars) ... (5 chars)". More like
      $ perl -Mstrict -wE'my $char = "0x388c818ca8b9251b398a736a67ccb19297"; substr($char, 5, -5, " ... "); say $char' 0x388 ... 19297
      (assuming the string is long enough)

        To remove the middle instead of keeping the middle, you could use

        substr( $char, 5, -5, "" ); # In-place
        or
        my $output = substr( $char, 0, 5 ) . substr( $char, -5 );
Re: remove chars with regex
by Marshall (Canon) on Feb 26, 2025 at 09:29 UTC
    use strict; use warnings; my $char = "0x388c818ca8b9251b393131c08a736a67ccb19297"; $char =~ s/^([0-9a-fx]{6}).+([0-9a-f]{6})$/$1 \.\.\. $2/; print $char; # 0x388c ... b19297

      Thanks @Marshall

Re: remove chars with regex
by choroba (Cardinal) on Feb 26, 2025 at 09:41 UTC
    To get the output you want, you don't need any look-arounds:
    my ($start, $end) = $char =~ /^(\S{6}).*(\S{6})$/;

    Note that it's six characters, not five. Also, don't forget to check the length of the string, as shorter strings won't match at all.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: remove chars with regex
by johngg (Canon) on Feb 26, 2025 at 11:05 UTC

    An alternative to using a regex is substr applied at either end of the string.

    johngg@aleatico:~$ perl -Mstrict -Mwarnings -E 'say q{}; my $char = q{0x388c818ca8b9251b393131c08a736a67ccb19297}; say join q{ ... }, substr( $char, 0, 6 ), substr( $char, length( $char ) - 6, 6 );' 0x388c ... b19297

    I hope this is helpful.

    Update: Re. AnonyMonk's comment regarding negative offsets, I had completely forgotten that, how dumb am I :-(

    Update 2: Here's the amended code.

    johngg@aleatico:~$ perl -Mstrict -Mwarnings -E 'say q{}; my $char = q{0x388c818ca8b9251b393131c08a736a67ccb19297}; say join q{ ... }, substr( $char, 0, 6 ), substr( $char, -6 );' 0x388c ... b19297

    Cheers,

    JohnGG

      FWIW, the second substr ... (for the last 6 characters) could be substr( $char, -6 ). Negative offsets are from the end, and if you omit the length you get all of the string after the start position.

Re: remove chars with regex
by hippo (Archbishop) on Feb 27, 2025 at 08:14 UTC

    Since there hasn't yet been a solution posted using lookarounds, here is one:

    use strict; use warnings; use Test::More tests => 1; my $have = '0x388c818ca8b9251b393131c08a736a67ccb19297'; my $want = '0x388c ... b19297'; $have =~ s/(?<=^.{6}).*(?=.{6}$)/ ... /; is $have, $want;

    Note that I probably would not do this in production and would instead use a substr-based approach.


    🦛