Or have a look at how file processing is done in the book "Learning Perl".
First, the one-liner:
$_ is Perl's default input and pattern-searching space. When you use the perl command-line interpreter with a file name and those options (plne), it opens the file for you, loops through each record and assigns each record to "$_".
So, with a "users.txt" file like the following -
a "print $_" will print each record as expected:
The option "p" will always print the line, so you can avoid typing "print". Like so -
But using it with the "s///" operator may give you unexpected results -
Which is why your regular expression works, but in an unintuitive way. The (square) brackets always match a single literal or a single character in a range.
So, [9] matches the digit "9", and [w-z] matches a single ASCII character in the range "w" through "z". The expression [$_] matches the first, and only the first, character of the input space. So, this -
substitutes the first character by a zero-length string. You do not need [$_] to match a single character. A dot "." is a regular expression for a single character. So, this -
works exactly the same way.
And so, the regex [$_]*_ is essentially the same as .*_ and both mean zero or more characters all the way up to the last underscore character ("_").
Thus, your one-liner should've been like so -
In a Perl program, @ARGV is an array of all input parameters, and if you pass a file name to it, then $ARGV[0] is the name of that file. This is not the same as $_.
Unlike the command-line perl interpreter, file handling (opening, looping, assigning to $_) is not done for you over here. You will have to do all that explicitly.
So, if your Perl program looks like this -
You won't see anything printed when you pass the file name as a parameter -
That because the file name "users.txt" is assigned to $ARGV[0] and that has nothing to do with $_.
You could check the value of the argument array (@ARGV) to get a better idea of what's happening:
Perl "flattens" the argument array and shows its elements as a string separated by single spaces. But you should know that in the second case, $ARGV[0] = "users.txt", $ARGV[1] = "users1.txt", $ARGV[2] = "users2.txt" and $ARGV[3] = "users3.txt".
Maybe printing it in a loop is clearer -
So this piece of code -
assigns the first element of the array @ARGV i.e. the file name parameter to $ID, but the next invocation to s/// operator tries to substitute the following regex:
$_ is uninitialized, remember? And so Perl throws that error message.
(You could initialize $_ and use it here, but that's beside the point.)
So what you want to do after you obtain the file name is, open the file, loop through the records, let Perl assign the record value to $_ implicitly and then call the s/// operator. Like so -
And then the Perl program will work as expected -
But Perl does a lot of things for you, without you asking for them. And that is true especially for Perl's default variable "$_". So when you say this -
Perl knows you meant this -
And when you say this -
Perl knows you meant this -
and so on...
So your program can be shortened to this -
HTH,
tyler_durden
Last edited by durden_tyler; 12-14-2010 at 10:10 AM..
These 2 Users Gave Thanks to durden_tyler For This Post:
I need to work with records having #AX in the EXP1 , please see my data sample and my attempt below:
$ cat xx
08:30:33 KEY1 (1255) EXP1 VAL:20AX0030006
08:30:33 KEY1 (1255) EXP1 VAL:20AX0030006
08:30:33 KEY1 (1255) EXP1 VAL:20AW0030006
08:30:33 KEY1 (1255) EXP1 VAL:20AW0030006
$ gawk '{... (1 Reply)
Hello All,
I have this script to awk IP to new file.
#awk '/myip|yourip/ {sub(/...\....\....\..../, newip)}1' newip=$IP existing.txt > new.txt
When existing.txt has myip=192.168.123.123 and $IP has 192.168.12.12, the awk script is not working. But while I add zero left padding to $IP i.e,... (3 Replies)
Hi,I've a unix pipe delimited file as below f1|f2|f3|f4|f5|f6 My requirement is to pad spaces on the left to fields f2, f3 and f5. Field Lengths according to file layout f2 - 4 char f3 - 5 char f5 - 3 char If my record is as below 1|43|bc|h0|34|a Output record should be as below 1| 43| bc|h0|... (4 Replies)
Hi guys,
I need AWK to merge the following 2 files:
file1
1 a 1 1
2 b 2 2
3 c 3 3
4 d 4 4
file2
a a/a c/c a/c c/c a/a c/t
c c/t c/c a/t g/g c/c c/t
desired output:
1 a 1 1 a/a c/c a/c c/c a/a c/t
2 b 2 2 x x x x x x
3 c 3 3 c/t c/c a/t g/g c/c c/t
4 d 4 4 x x x x x x (2 Replies)
Hi guys,
I need to use awk to join 2 files
file_1
A 001
B 002
C 003
file_2
A XX1
B XX2
output desired
A 001 XX1
B 002 missing
C 003 XX2
thank you! (2 Replies)
I am passing input string,length, and the pad character.
input string=123
Pad char=#
Length=6
then the output should be:
###123
How we can do this?
Thanks (5 Replies)
So I have 2 files:
File 1:
111,Mike,Stipe
222,Peter,Buck
333,Mike,Mills
File 2:
222,Mr,Bono
444,Mr,Edge
I want output to be below, where 222 records joined and all none joined records still in output
111,Mike,Stipe
222,Peter,Buck,Mr,Bono
333,Mike,Mills
444,Mr,Edge (4 Replies)
Hi guys
I have variable that contains a full directory path.
var=/tmp/a/b/c/d
I want to be able to extract different directories in the path right to left while using / as the delimiter.
so for e.g. if in the above example if I want c then I want it to be in the middle of 1st and... (2 Replies)
Fallowing is the input file that is pipe seperated.
is it possible to generated the report that is alligned left justifed as that of sample output.
I apprecitae your help on this.
InputFile (temp.txt):
108005555|001|christina.lipski||Submitter... (3 Replies)