27

Example:

use strict;
my $file = shift;

open(IN, $file) || die "Unable to open $file\n";
open(OUT, ">$file.$$") or die $!;

What is going on with the my $file = shift?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sean curran
  • 279
  • 1
  • 3
  • 3
  • this is a common Perl idiom, please read [`perldoc perlintro`](http://perldoc.perl.org/perlintro.html#Writing-subroutines) for common use of Perl. – Joel Berger Aug 17 '11 at 14:18
  • Is the problem that you don't know the difference between `"shift"` and `shift()`? – tchrist Aug 18 '11 at 02:20
  • Exact duplicate of *[What does shift() do in Perl?](https://stackoverflow.com/questions/296964/what-does-shift-do-in-perl)*. – Peter Mortensen Jan 12 '18 at 15:59

4 Answers4

32

If used in the main program, it will shift (remove and return) the first value from @ARGV, the argument list of your program. If used inside a subroutine, it will shift the first value from @_, the argument list of the sub. See the documentation for more info.

TLP
  • 66,756
  • 10
  • 92
  • 149
  • For local documentation of built-in functions: perldoc -f shift (Ubuntu, at least, will need you to install the perl-doc package for this to work, but tells you so when you try it). – ijw Aug 17 '11 at 11:33
  • 1
    Forgive me but this seems like the worst convention ever for code readability. – MrBrightside May 31 '14 at 00:22
  • 1
    @CynicalOptimist It is only confusing the first time you see it, unless you have a rather bad memory for details. – TLP May 31 '14 at 12:46
  • 1
    I respect you're opinion, but I have to disagree for the guy who's reading it. For the guy writing it, probably not terrible... – MrBrightside May 31 '14 at 17:04
  • 1
    @CynicalOptimist I think people often are unfair when it comes to Perl. There are precious few languages that you can understand completely without consulting a manual, why would Perl be any different? I don't understand why people think that. – TLP Jun 01 '14 at 15:34
16

You can read the documentation on shift. It is very clear. shift accepts an array and extracts the first element (actually removing it from the array). If you don't provide any array, it uses @ARGV (the arguments to the command line of the program) to read the data. If you're inside a function, it uses @_, namely, the parameters of the function.

Example:

my @array = (1, 2, 3);
my $value = shift @array;
print $value; # will print '1'
Diego Sevilla
  • 28,636
  • 4
  • 59
  • 87
5

shift uses the @_ variable which contains the values passed to a function or shift uses @ARGV for the values passed to the script itself if shift is referenced outside of a function.

ONE WORD OF CAUTION: It is probably wise, especially in Windows where many paths contain spaces, to put the filename and path in single quotes when you pass it to the script or function. This will tell Perl that you are passing it a single scalar value rather than an array of values. You can use double quotes if you want to interpolate part of the name. For example:

my $path = 'C:\Goat Kids';
func("$path\\goat.txt");

Or, from the command line if you are passing the filename directly to the script:

perl goat.pl "C:\Goat Kids\goat.txt"
Smartnor
  • 51
  • 4
  • 1
    Careful, single quotes don't mean the same thing in a Windows command line as they do in a Unix shell. If you type `perl goat.pl 'C:\Goat Kids\goat.txt'` in a Windows command shell, `goat.pl` will see an argument with single quotes. – Keith Thompson Aug 17 '11 at 02:40
  • I corrected it. Thanks. I generally do not use command line options because most of my users just want to double-click the script to run it. However, I write scripts that call functions with filenames as parameters on a very frequent basis. – Smartnor Aug 17 '11 at 03:12
  • 1
    Welcome to StackOverflow. This is a question and answer site, not a newsgroup or discussion forum. It works by someone asking a question, and then people can post answers to the question by typing into the "Your Answer" area. Your post is not an answer to the question asked ("I agree the other answers are good"), and should not appear as one. If you haven't already, please take a few minutes to read the [FAQ](http://stackoverflow.com/faq) and a few other questions to see how the site is designed to work. Thanks. – Ken White Aug 18 '11 at 01:06
5

The previous answers have described how shift works. I would like to comment on why it is a good idea to use it in your own programs.

Perl by default is a pass-by-reference language. If a subroutine modifies its argument, the caller will see these, sometimes unexpected, changes. It is a good practice to use shift to assign a subroutine argument to a private variable. This way, if you make any changes to it, it will not be visible to the caller. E.g., the code below outputs

1
2
2

The first subroutine modifies its argument and the caller sees the change. The second subroutine modifies a private copy of its argument, and this change is not visible in the caller.

use strict;
use warnings;

sub pass_by_ref {
    $_[0] = 2;
}

sub pass_by_value {
    my $x = shift @_;
    $x = 3;
}

my $x = 1;
print $x, "\n";
pass_by_ref($x);
print $x, "\n";
pass_by_value($x);
print $x, "\n";