Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

cut of first char of a string

by holli (Abbot)
on Mar 08, 2005 at 08:06 UTC ( [id://437447]=perlquestion: print w/replies, xml ) Need Help??

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

Challenge:

How many ways does Perl have to cut off the first char of a string?
conditions:
  • no additional variables.
  • no self-written subroutines

Here are the obvious solutions:
use strict; my $s = "123456789"; substr($s,0,1)=""; print "$s\n"; $s =~ s/^.//; print "$s\n"; $s = reverse $s; chop $s; $s = reverse $s; print "$s\n";
I guess you can up with more?


holli, /regexed monk/

Replies are listed 'Best First'.
Re: cut of first char of a string
by Corion (Patriarch) on Mar 08, 2005 at 08:17 UTC

      of which I find the name chip especially cute

      I like chimp for the counterpart of chomp even better =)

      Cheers, Sören

Re: cut of first char of a string
by sh1tn (Priest) on Mar 08, 2005 at 08:20 UTC
    $_ = '12345'; $_ = join '',(split/^./);


      Very nice++. I really like this one.


      holli, /regexed monk/
Re: cut of first char of a string
by davido (Cardinal) on Mar 08, 2005 at 08:19 UTC

    Is there any kind of sanity check to pass? If not...

    # One way... $s = join '', ( split //, $s )[ 1 .. length($s) - 1 ]; print $s, $/;

    Update: And another.....

    $s = pack 'A*', unpack( 'xA*', $s ); # ASCII only, please ;) print $s, $/;

    Dave

      $s = pack 'A*', unpack( 'xA*', $s ); # ASCII only, please ;)
      I see no reason for the pack. And you're better of using 'a*' not 'A*', unless you really want to trim trailing spaces.
      $s = unpack 'xa*', "qwerty "; print "'$s'\n";
Re: cut of first char of a string
by bart (Canon) on Mar 08, 2005 at 10:13 UTC
    More split silliness.
    (undef, $s) = split //, $s, 2;

    The 3rd parameter 2 makes split split into only 2 parts. I then simply ignore the first part.

      Note that your solution makes $s undefined if $s was equal to the empty string. chop doesn't undef an empty string.
Re: cut of first char of a string
by borisz (Canon) on Mar 08, 2005 at 08:38 UTC
    $s = unpack "xA*", $s; $s = substr($s, 1); substr($s, 0, 1, "");
    Update: remove wrong $s = in the last substr thanks to nothingmuch.
    Boris
      In the last one didn't you mean without $s =?
      -nuffin
      zz zZ Z Z #!perl
Re: cut of first char of a string
by chb (Deacon) on Mar 08, 2005 at 10:27 UTC
    This uses a core module (and is Sick And Twisted(TM)):
    use strict; use warnings; use Math::BigInt; my $s = 'Hello World'; $s = reverse ((Math::BigInt->new('0b' . (unpack('B*', $s) & ('00000000' . ('11111111' x (length($s) - 1))))))->as_bin()) +; $s =~ s!b0!!; $s = reverse(pack('b*', $s)); print "'", $s, "'\n";
Re: cut of first char of a string
by ambrus (Abbot) on Mar 08, 2005 at 12:08 UTC

      I especially like the last one (six 's's. Hmm, would that be six-σ?). Very cool.

      --MidLifeXis

Re: cut off first char of a string
by Roy Johnson (Monsignor) on Mar 08, 2005 at 12:08 UTC
    I haven't seen these posted yet:
    ($_) = /.(.*)/s; # or $_ = substr($_, -length($_)+1); # or /./s and $_ = $';

    Caution: Contents may have been coded under pressure.
Re: cut of first char of a string
by rinceWind (Monsignor) on Mar 08, 2005 at 12:37 UTC
    There's a whole aspect of this question which nobody has touched on yet. I'm talking about the precise meaning of "first char". Consider the situation when $s is a utf-8 string. The first "character" could be several bytes long.

    This means that the regexp and chop methods will work on full "characters", but substr operates on "bytes".

    I attended a talk recently at london.pm on this subject, the slides of which are here.

    --
    I'm Not Just Another Perl Hacker

      This means that the regexp and chop methods will work on full "characters", but substr operates on "bytes".

      AFAIK unless the use bytes pragma is in effect substr operates on characters, not on bytes. Maybe the behaviour you describe is true pre 5.8.x but it isnt true in 5.8:

      D:\Development>perl5.8.5 -le "my $str='ba'.pack('U',0x0370).'!'; print +f qq'$_ : %d\n', ord(substr($str,$_,1)) for 0..length($str)-1" 0 : 98 1 : 97 2 : 880 3 : 33 D:\Development>perl5.8.5 -Mbytes -le "my $str='ba'.pack('U',0x0370).'! +'; printf qq'$_ : %d\n', ord(substr($str,$_,1)) for 0..length($str)-1 +" 0 : 98 1 : 97 2 : 205 3 : 176 4 : 33
      ---
      demerphq

Re: cut of first char of a string
by Limbic~Region (Chancellor) on Mar 08, 2005 at 13:50 UTC
    holli,
    If we are just being silly:
    $str = $_->[0] ? $str . $_->[1] : '' for map { [ $_, substr($str,$_,1) + ] } 0 .. length($str) - 1;

    Cheers - L~R

Re: cut of first char of a string
by japhy (Canon) on Mar 08, 2005 at 15:31 UTC
    What a shame we can't write functions and what-not. I'd say the best way is to write an XS module that increments the SV's IV value, sets the OOK flag, and decrements its CUR value:
    % perl -MDevel::Peek $x = "japhy"; Dump($x); $x =~ s/\C//; Dump($x); __END__ SV = PV(0x814ce90) at 0x81603ac REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x815d008 "japhy"\0 CUR = 5 LEN = 6 SV = PVIV(0x814d2a0) at 0x81603ac REFCNT = 1 FLAGS = (POK,OOK,pPOK) IV = 1 (OFFSET) PV = 0x815d009 ( "j" . ) "aphy"\0 CUR = 4 LEN = 5
    _____________________________________________________
    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: cut of first char of a string
by Anonymous Monk on Mar 08, 2005 at 08:51 UTC
    Not necessary '^' metasym:
    my $s = "123456789"; $s =~ s/.//

      This doesn't do 'the right thing' for strings starting with a newline (which admittedly is a border case):

      perl -MData::Dumper -e "$foo=qq(\nHello);$foo =~ s/.//; print Dumper \ +$foo"

      Adding the /s flag makes dot match newline too:

      perl -MData::Dumper -e "$foo=qq(\nHello);$foo =~ s/.//s; print Dumper +\$foo"
Re: cut of first char of a string
by TimToady (Parson) on Mar 10, 2005 at 08:41 UTC
    Well, if you don't count $_ as an extra variable because it's already implicitly there, you can do it like this:
    use bytes; if (vec($s,3,2) < 3) { vec($s,$_,8) = vec($s,$_+1,8) for 0..length($s)-2; chop($s); } else { vec($s,$_,8) = vec($s,$_+1,8) for 0..length($s)-2; chop($s); while (vec($s,3,2) == 2) { vec($s,$_,8) = vec($s,$_+1,8) for 0..length($s)-2; chop($s); } }
    Update:
    Hmm, here's a solution without $_:
    use bytes; if (vec($s,3,2) < 3) { () = $s =~ m/.(?=.)(?{ vec($s,pos($s)-1,8) = vec($s,pos($s),8) +})/sg; chop($s); } else { () = $s =~ m/.(?=.)(?{ vec($s,pos($s)-1,8) = vec($s,pos($s),8) +})/sg; chop($s); while (vec($s,3,2) == 2) { () = $s =~ m/.(?=.)(?{ vec($s,pos($s)-1,8) = vec($s,pos($s +),8)})/sg; chop($s); } }
Re: cut of first char of a string
by cog (Parson) on Mar 08, 2005 at 10:42 UTC
    Actually, this:

    $s =~ s/^.//; print "$s\n";

    Could be written as:

    $s =~ s/.//; print "$s\n";

    Update: I had assumed the string would only contain the regular \w characters; won't work for strings starting with \n, obviously (because the dot doesn't match newlines). See Re: cut of first char of a string.

Re: cut of first char of a string
by jbrugger (Parson) on Mar 08, 2005 at 09:46 UTC
    #!/bin/perl use strict; my $s = "Hello world!"; print substr($s,1,length($s));
Re: cut of first char of a string
by Anonymous Monk on Mar 08, 2005 at 10:25 UTC
    Some variations on four themes: substr($s, 0, 1, ""), $s =~ s/.//s;, and use of split and unpack.
    $s = (split /./s, $s, 2)[1] err ""; # Needs 'defined-or' patch, or 5.9 +.1 $s = (split /./s, $s, 2)[1]; $s = "" unless defined $s; $s = length $s ? (split /./s, $s, 2)[1] : ""; $s = join "", map {substr $s, $_, 1} grep {$_} 0 .. length($s)-1; substr $s, $_, 1, $_ ? substr($s, $_, 1) : "" for 0 .. length($s)-1; local $a = 0; $s = join "", grep {$a++} split //, $s; local $" = ""; $s = "@{[(split //, $s)[1 .. length($s)-1]]} $s =~ s/(?<!.).//sg; local $a; $s =~ s/.(??{$a++ ? "(?!)" : "(?=)"})//sg; $s = pack "A*", (unpack "A*", $s)[1 .. length($s)-1]; $s = pack "A*", unpack "xA*", $s if length $s; $s = pack "A*", unpack "xA@{[length($s)-1]}", $s if length $s;
Re: cut of first char of a string
by sh1tn (Priest) on Mar 08, 2005 at 12:24 UTC
    First, but not last:
    $_ = '12345';s/(.(.*))/$2or$1/e


      That doesn't work correctly:
      perl -wle '$_ = '10'; s/(.(.*))/$2or$1/e; print' 10
        Yes, that doesn't, but this does:
        s/(.(.*))/($2ne'')?$2:$1/e


Re: cut of first char of a string
by blazar (Canon) on Mar 08, 2005 at 13:10 UTC
    How many ways How many ways does Perl have to cut off the first char of a string?
    At a first glance it seems that this has not been mentioned yet, although basically it may be thought of as a variation of several of those that have been:
    $ perl -lne 'print for /(.)(.*)/' dfdfsdgdfs d fdfsdgdfs stgsghttsthe s tgsghttsthe
Re: cut of first char of a string
by eisforian (Novice) on Mar 08, 2005 at 15:31 UTC
    Silly and convoluted:
    $s = "12345678"; $s = join '', ( split //, $s )[ ( sprintf( '%03d%03d', length($s), length($s) ) / 7 / 11 / 13 - sprintf( '%03d', length($s) ) + 1 ) .. length($s) - 1 ]; print "$s\n";
Re: cut of first char of a string
by Joost (Canon) on Mar 08, 2005 at 15:58 UTC
Re: cut of first char of a string
by Jasper (Chaplain) on Mar 08, 2005 at 15:46 UTC
    $_ = $' x /./

    edit: damn, I see Roy already had this (effectively)
Re: cut of first char of a string
by calin (Deacon) on Mar 08, 2005 at 16:57 UTC

    This does not exactly meet your requirements (no additional vars), but since everybody is going for crazy solutions and I have time to kill, here it is:

    use v5.8; $s = "abcdef"; # or initialize it yourself ($s, $_) = (undef, $s); $s.=???!??:$&while/./g; print "$s\n";

    Warning: Does not work correctly under Perls earlier than 5.8 (change in semantics). It can be fixed though, at the expense of aesthetics.

Re: cut of first char of a string
by Anonymous Monk on Mar 08, 2005 at 17:17 UTC
    How many ways does Perl have to cut off the first char of a string?

    An infinite number, of course.

    For example, there are an infinite number of variations of the following solution:

    Append a string known not to be within the string, move the first character after the unique tag, then remove everything after the unique tag.

    You can increase the length of the unique tag string towards infinity, and you'll get an infinite number of solutions.
    --
    Ytrew

      $_ = '12345';$_ = join'',(@{[split//]}[1..@{[split//]}]) # ?


Re: cut of first char of a string
by Whitehawke (Pilgrim) on Mar 12, 2005 at 05:56 UTC

    Well, here's a couple of simple ones:

    print join'',@{[do{shift@{$s=[split//,$s='foobarbaz']};@$s}]} print $s=reverse@{$s=do{pop @{$s=[split//,reverse$s='foobarbaz']};$s}}
    Although, I'm honestly not sure why the $s= that immediately precedes the do is necessary in the second one. Can anyone explain it to me?
      I'm not sure but I think it's needed because you assign an anonymous array to $s before it, so if you do not set $s, the rightmost $s will give that array.
Re: cut of first char of a string
by sh1tn (Priest) on Mar 10, 2005 at 06:43 UTC
    $_='0123456789' ;s;.(?=(.+));$1;s&&s;(.+)(\1);$1;s;


Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://437447]
Approved by sh1tn
Front-paged by rob_au
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (6)
As of 2024-04-18 10:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found