When I started with variables to print a variable $foo in a string
I used print ${foo}s but when I used print "$(foo)s"
it gave me
1000 4 24 27 30 46 108 125 1000)s . When I printed $( or $) it gives me the sequence 1000 4 24 27 30 46 108 125 1000 . Also
$[ gave 5.014002 and $] gave 0 . What do they mean?
$( = The real gid of this process.
$[ = This variable stores the index of the first element in an array, and of the first character in a substring. The default is 0.
$) = The effective gid of this process.
$] = Perlversion
seen here: http://perldoc.perl.org/perlvar.html
See perldoc perlvar (in fact, see it any time you have a question about $ followed by a symbol).
$( and $) give the real and effective gids of the process.
You get a space separated list of gids if the system supports membership in multiple groups simultaneously.
$[ is the index considered to be the first element of an array.
$] is an old way to get the version of Perl being used to run the program.
Related
I have 2 commands that I need to run back to back 16 times for 2 sets of data. I have labeled the files used as file#a1_100.gen (set 1) and file#a2_100.gen (set 2). The 100 is then replaced by multiples of 100 upto 1600 (100,200,...,1000,...,1600).
Example 1: For first set
Command 1: perl myprogram1.pl file#a1.pos abc#a1.ref xyz#a1.ref file#a1_100.gen file#a1_100.out
Command 2: perl my program2.pl file#a1_100.out file#a1_100.out.long
Example 2: For first set
Command 1: perl myprogram1.pl file#a1.pos abc#a1.ref xyz#a1.ref file#a1_200.gen file#a1_200.out
Command 2: perl my program2.pl file#a1_200.out file#a1_200.out.long
These 2 commands are repeated 16 times for both set 1 and set 2. For set 2 the filename changes to File#a2...
I need a command that will run this on its own by changing the filename for the 2 sets, running it 16 times for each set.
Any help will be greatly appreciated! Thanks!
This is probably most easily done with a shell script. As with Perl, TMTOWTDI — there's more than one way to do it.
for num in $(seq 1 16)
do
perl myprogram1.pl file#a1.pos abc#a1.ref xyz#a1.ref file#a1_${num}00.gen file#a1_${num}00.out
perl myprogram2.pl file#a1_${num}00.out file#a1_${num}00.out.long
done
(You could use {1..16} in place of $(seq 1 16) to generate the numbers. You might also note that the # characters in the file names discombobulate the SO Markdown system.)
Or you could use:
for num in $(seq 100 100 1600)
do
perl myprogram1.pl file#a1.pos abc#a1.ref xyz#a1.ref file#a1_${num}.gen file#a1_${num}.out
perl myprogram2.pl file#a1_${num}.out file#a1_${num}.out.long
done
(I don't think there's a {...} expansion for that.)
Or, better, you could use variables to hold values to avoid repetition:
POS="file#a1.pos"
ABC="abc#a1.ref"
XYZ="xyz#a1.ref"
for num in $(seq 100 100 1600)
do
PFX="file#a1_${num}"
GEN="${PFX}.gen"
OUT="${PFX}.out"
LONG="${OUT}.long"
perl myprogram1.pl "${POS}" "${ABC}" "${XYZ}" "${GEN}" "${OUT}"
perl myprogram2.pl "${OUT}" "${LONG}"
done
In this code, the braces around the parameter names are all optional; in the first block of code, the braces around ${num} were mandatory, but optional in the second set. Enclosing names in double quotes is also optional here, but recommended.
Or, if you must do it in Perl, then:
use warnings;
use strict;
my $POS = "file#a1.ref";
my $ABC = "abc#a1.ref";
my $XYZ = "xyz#a1.ref";
for (my $num = 100; $num <= 1600; $num += 100)
{
my $PFX = "file#a1_${num}";
my $GEN = "${PFX}.gen";
my $OUT = "${PFX}.out";
my $LONG = "${OUT}.long";
system("perl", "myprogram1.pl", "${POS}", "${ABC}", "${XYZ}", "${GEN}", "${OUT}");
system("perl", "myprogram2.pl", "${OUT}", "${LONG}");
}
This is all pretty basic coding. And you can guess that it didn't take me long to generate this from the last shell script. Note the use of multiple separate strings instead on one long string in the system calls. That avoids running a shell interpreter — Perl runs perl directly.
You could use $^X instead of "perl" to ensure that you run the same Perl executable as ran the script shown. (If you have /usr/bin/perl on your PATH but you run $HOME/perl/v5.20.1/bin/perl thescript.pl, the difference might matter, but probably wouldn't.)
Lets say i have a file like below:
And i want to store all the decimal numbers in a hash.
hello world 10 20
world 10 10 10 10 hello 20
hello 30 20 10 world 10
i was looking at this
and this worked fine:
> perl -lne 'push #a,/\d+/g;END{print "#a"}' temp
10 20 10 10 10 10 20 30 20 10 10
Then what i need was to count number of occurrences of each regex.
for this i think it would be better to store all the matches in a hash and assign an incrementing value for each and every key.
so i tried :
perl -lne '$a{$1}++ for ($_=~/(\d+)/g);END{foreach(keys %a){print "$_.$a{$_}"}}' temp
which gives me an output of:
> perl -lne '$a{$1}++ for ($_=~/(\d+)/g);END{foreach(keys %a){print "$_.$a{$_}"}}' temp
10.4
20.7
Can anybody correct me whereever i was wrong?
the output i expect is:
10.7
20.3
30.1
although i can do this in awk,i would like to do it only in perl
Also order of the output is not a concern for me.
$a{$1}++ for ($_=~/(\d+)/g);
This should be
$a{$_}++ for ($_=~/(\d+)/g);
and can be simplified to
$a{$_}++ for /\d+/g;
The reason for this is that /\d+/g creates a list of matches, which is then iterated over by for. The current element is in $_. I imagine $1 would contain whatever was left in there by the last match, but it's definitely not what you want to use in this case.
Another option would be this:
$a{$1}++ while ($_=~/(\d+)/g);
This does what I think you expected your code to do: loop over each successful match as the matches happen. Thus the $1 will be what you think it is.
Just to be clear about the difference:
The single argument for loop in Perl means "do something for each element of a list":
for (#array)
{
#do something to each array element
}
So in your code, a list of matches was built first, and only after the whole list of matches was found did you have the opportunity to do something with the results. $1 got reset on each match as the list was being built, but by the time your code was run, it was set to the last match on that line. That is why your results didn't make sense.
On the other hand, a while loop means "check if this condition is true each time, and keep going until the condition is false". Therefore, the code in a while loop will be executed on each match of a regex, and $1 has the value for that match.
Another time this difference is important in Perl is file processing. for (<FILE>) { ... } reads the entire file into memory first, which is wasteful. It is recommended to use while (<FILE>) instead, because then you go through the file line by line and keep only the information you want.
When I found Perl's $^O, I was curious whether there are more variables like this, because ^ reminded me of a regular expression. When I enter
print "$(^b)";
it comes up with some numbers:
1000 81 90 91 92 93 100 150 1000
What to these mean? Is this some kind of 0xdeadbeef?
I think you are just printing out the value of $(.
The real gid of this process. If you are on a machine that supports membership in multiple groups simultaneously, gives a space separated list of groups you are in. The first number is the one returned by getgid() , and the subsequent ones by getgroups() , one of which may be the same as the first number.
However, a value assigned to $( must be a single number used to set the real gid. So the value given by $( should not be assigned back to $( without being forced numeric, such as by adding zero. Note that this is different to the effective gid ($) ) which does take a list.
You can change both the real gid and the effective gid at the same time by using POSIX::setgid() . Changes to $( require a check to $! to detect any possible errors after an attempted change.
Here is the comparison:
diff <(perl -le 'print "$(";') <(perl -le 'print "$(^b)";')
1c1
< 20 20 402 12 33 61 79 80 81 98 100 204 401
---
> 20 20 402 12 33 61 79 80 81 98 100 204 401^b)
See the documentation on perldoc perlvar for a list of all the various built-in variables (along with their use English; equivalent names).
Guys perl is not as easy i thought its so confusing thing.I just moved to operators and I wrote some codes but I am unable to figure it out how the compiler treating them.
$in = "42" ;
$out = "56"+32+"good";
print $out,;
The output for above code is 88 and where does the good gone? and Now lets see the other one.
$in ="42";
$out="good52"+32;
print $out ;
and for these the output is 32. The question is where does the good gone that we just stored in $out and the value 52 between the " "why the compiler just printing the value as 32 but not that remaining text.And the other question is
$in=52;
$in="52";
both doing the same work "52" not working as a text . becuase when we add "52"+32 it gives as 84. what is happening and
$in = "hello";
$in = hello;
both do the same work ? or do they differ but if i print then give the same output.Its just eating up my brain.Its so confusing becuase when "52" or 52 and "hello" or hello doing the same job why did they introduce " ".I just need the explaination why its happening for above codes.
In Perl, + is a numeric operator. It tries to interpret its two operands as numbers. 51 is the number 51. "51" is a string containing two digits, and the + operator tries to convert the string to a number, which is 51, and uses it in the calculation. "hello" is a string containing five letters, and when the + operator tries to interpret that as a number, it equates to 0 (zero).
Your first example is thus:
$out = "56"+32+"good";
which is evaluates just like:
$out = 56 + 32 + 0;
Your print then converts that to a string on output, and yields 88.
In perl, the + operator will treat its arguments as numbers, and try to convert anything that is not a number to a number. The . (dot) operator is used to join strings: it will try to convert its operands to strings if they aren't already strings.
If you put:
use strict;
use warnings;
At the top of your script, you would get warnings such as:
Argument "good" isn't numeric in addition (+) at ...
Argument "good52" isn't numeric in addition (+) at ...
Perl automatically reassigns a string value to numeric, if possible. So "42" + 10 actually becomes 52. But it cannot do that with a proper string value, such as "good".
In perl, a string in a numerical context (like when you use a + operator) is converted to a number.
In perl, you can concatenate string using the . (dot) operator, not +.
If you use +, perl will try and interpret all of the operands as numbers. This works well for strings that are number representations, otherwise you get 0. This explains what you see.
$in=52;
$in="52";
both doing the same work "52" not working as a text . becuase when we add "52"+32 it gives as 84.
The problem here is not with the variable definition. One is a string and the other a number. But when you use the string in a numerical expression (+), then it will converted to number.
About your second question:
$in = "hello" defines a string, as you expect;
$in = hello; will just copy the symbol hello (however it is defined) on to your variable. This is actually not "strict" perl and if you set use strict; in your file, perl will complain about it.
First off, give this a read.
Your problem is that the + is a mathematical addition, which doesn't work on strings. If you use that, Perl will assume that you're working with numbers and therefore discard anything that isn't.
To concatenate strings, use .:
$str = "blah " . "blah " . "blah";
As far as the difference between "52" and 52 goes, there isn't one. Since nothing (commands, comments, etc.) in Perl can start with numbers, the compiler doesn't need the quotes to know what to do.
Suppose I have a filehandle $fh. I can check its existence with -e $fh or its file size with -s $fh or a slew of additional information about the file. How can I get its last modified time stamp?
Calling the built-in function stat($fh) returns an array with the following information about the file handle passed in (from the perlfunc man page for stat):
0 dev device number of filesystem
1 ino inode number
2 mode file mode (type and permissions)
3 nlink number of (hard) links to the file
4 uid numeric user ID of file's owner
5 gid numeric group ID of file's owner
6 rdev the device identifier (special files only)
7 size total size of file, in bytes
8 atime last access time since the epoch
9 mtime last modify time since the epoch
10 ctime inode change time (NOT creation time!) since the epoch
11 blksize preferred block size for file system I/O
12 blocks actual number of blocks allocated
Element number 9 in this array will give you the last modified time since the epoch (00:00 January 1, 1970 GMT). From that you can determine the local time:
my $epoch_timestamp = (stat($fh))[9];
my $timestamp = localtime($epoch_timestamp);
Alternatively, you can use the built-in module File::stat (included as of Perl 5.004) for a more object-oriented interface.
And to avoid the magic number 9 needed in the previous example, additionally use Time::localtime, another built-in module (also included as of Perl 5.004). Together these lead to some (arguably) more legible code:
use File::stat;
use Time::localtime;
my $timestamp = ctime(stat($fh)->mtime);
Use the builtin stat function. Or more specifically:
my $modtime = (stat($fh))[9]
my #array = stat($filehandle);
The modification time is stored in Unix format in $array[9].
Or explicitly:
my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
$atime, $mtime, $ctime, $blksize, $blocks) = stat($filepath);
0 dev Device number of filesystem
1 ino inode number
2 mode File mode (type and permissions)
3 nlink Number of (hard) links to the file
4 uid Numeric user ID of file's owner
5 gid Numeric group ID of file's owner
6 rdev The device identifier (special files only)
7 size Total size of file, in bytes
8 atime Last access time in seconds since the epoch
9 mtime Last modify time in seconds since the epoch
10 ctime inode change time in seconds since the epoch
11 blksize Preferred block size for file system I/O
12 blocks Actual number of blocks allocated
The epoch was at 00:00 January 1, 1970 GMT.
More information is in stat.
You need the stat call, and the file name:
my $last_mod_time = (stat ($file))[9];
Perl also has a different version:
my $last_mod_time = -M $file;
but that value is relative to when the program started. This is useful for things like sorting, but you probably want the first version.
If you're just comparing two files to see which is newer then -C should work:
if (-C "file1.txt" > -C "file2.txt") {
{
/* Update */
}
There's also -M, but I don't think it's what you want. Luckily, it's almost impossible to search for documentation on these file operators via Google.
You could use stat() or the File::Stat module.
perldoc -f stat
I think you're looking for the stat function (perldoc -f stat)
In particular, the item found at index 9 of the returned list (i.e., the 10th field) is the last modify time of the file, in seconds since the epoch.
So:
my $last_modified = (stat($fh))[9];
On my FreeBSD system, stat just returns a bless.
$VAR1 = bless( [
102,
8,
33188,
1,
0,
0,
661,
276,
1372816636,
1372755222,
1372755233,
32768,
8
], 'File::stat' );
You need to extract mtime like this:
my #ABC = (stat($my_file));
print "-----------$ABC['File::stat'][9] ------------------------\n";
or
print "-----------$ABC[0][9] ------------------------\n";
This is very old thread, but I tried using the solution and could not get the information out of File::stat. (Perl 5.10.1)
I had to do the following:
my $f_stats = stat($fh);
my $timestamp_mod = localtime($f_stats->mtime);
print "MOD_TIME = $timestamp_mod \n";
Just thought I share in case anyone else had the same trouble.