CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
command line option -n , -p with multiple files...

 



alex5161
Novice

May 30, 2017, 10:43 AM

Post #1 of 7 (3040 views)
command line option -n , -p with multiple files... Can't Post

 I am looking for help in processing of those options: '-n' or '-p'
I understand what they do and how to use them.
But, I would like to use them with more than one file (and without any shell-loop; loading the 'perl' once.)
I did try it and '-n' works on 2 files.
Question is:
- is it possible to distinguish from which file is a printed line?

So, I use command like:

Code
perl -ne 'print "  $.: $_" if  /"\d\d"/' ./fl1 ./fl2

It have correctly selected lines, but I would like anyhow to get a file name where from each line is selected.
Not sure how to get it, if that is possible at all in such usage...

I understand the perl is using the

Code
 while (<>) {...}

I am not sure what is going to be the '<>'
- does it already concatenated in shell files, mentioned as arguments?
Or perl do it inside somehow?
Maybe it opening each file as standard-input?!
If so, is it possible to get its name?

Will appreciate help, if you get some idea!
(I understand, I could write everything without the '-n' or '-p', but would like to have that shortage be used,... if possible)
Thanks.


BillKSmith
Veteran

May 30, 2017, 1:59 PM

Post #2 of 7 (3035 views)
Re: [alex5161] command line option -n , -p with multiple files... [In reply to] Can't Post

It can be done, but it is not easy. You have to study the pseudo code for <> in the IO OPERATORS section of perlop to understand what is going on. I devised the following demo. You have to keep track of the current file yourself.

Code
C:\Users\Bill\forums\guru\alex>type a.txt 
I am from file 'a'.

C:\Users\Bill\forums\guru\alex>type b.txt
I am from file 'b'.

C:\Users\Bill\forums\guru\alex>type c.txt
I am from file 'c'.

C:\Users\Bill\forums\guru\alex>type test.pl
#! /usr/bin/perl -n
use strict;
use warnings;
BEGIN{
print "BEGIN: @ARGV\n";
our $CUR_FILE_NAME = $ARGV[0];
our $NEXT_FILE_NAME = $ARGV[1];
}
our $CUR_FILE_NAME;
our $NEXT_FILE_NAME;


if (!defined $ARGV[0] or $NEXT_FILE_NAME ne $ARGV[0]) {
$CUR_FILE_NAME= $NEXT_FILE_NAME;
$NEXT_FILE_NAME= $ARGV[0];
}
print $CUR_FILE_NAME, ': ', $_, "\n";

C:\Users\Bill\forums\guru\alex>test.pl a.txt b.txt c.txt
BEGIN: a.txt b.txt c.txt
a.txt: I am from file 'a'.

b.txt: I am from file 'b'.

c.txt: I am from file 'c'.


UPDATE: The name of the current input file in available in the special variable $ARGV. This is documented in the section of perlop on the operator <>.
Good Luck,
Bill

(This post was edited by BillKSmith on May 30, 2017, 2:48 PM)


FishMonger
Veteran / Moderator

May 30, 2017, 2:14 PM

Post #3 of 7 (3035 views)
Re: [alex5161] command line option -n , -p with multiple files... [In reply to] Can't Post

I have not done any testing, but in order for $. to reset for each file, you'll need to explicitly close the filehandle after testing for eof. The filehandle is ARGV (not sure if it needs to be upper or lowercase).


(This post was edited by FishMonger on May 30, 2017, 2:15 PM)


alex5161
Novice

Jun 1, 2017, 6:05 AM

Post #4 of 7 (2991 views)
Re: [FishMonger] command line option -n , -p with multiple files... [In reply to] Can't Post

 I have reasonable answer on another forum: http://www.unix.com/shell-programming-and-scripting/272779-perl-command-line-option-n-p-multiple-files-can-know-file-name-printed-line.html#post302998343
Generally, it is about that the '<>' receives the files from the @ARGV one-by-one (probably, by 'shift' command) into the $ARGV and that could be used perfectly.
Here is my example (based on solution from mentioned forum):

Code
/tst > for fl in fl{1..3}; do echo -e " this is $fl file\n Ending $fl file line\n">$fl; done 
/tst > perl -ne 'if ($cr ne $ARGV){$.=1;$cr=$ARGV;} print "$cr(\$ARGV[0]=$ARGV[0]): $. - $_";' fl[0-3]
fl1($ARGV[0]=fl2): 1 - this is fl1 file
fl1($ARGV[0]=fl2): 2 - Ending fl1 file line
fl1($ARGV[0]=fl2): 3 -
fl2($ARGV[0]=fl3): 1 - this is fl2 file
fl2($ARGV[0]=fl3): 2 - Ending fl2 file line
fl2($ARGV[0]=fl3): 3 -
fl3($ARGV[0]=): 1 - this is fl3 file
fl3($ARGV[0]=): 2 - Ending fl3 file line
fl3($ARGV[0]=): 3 -
/tst >



BillKSmith
Veteran

Jun 1, 2017, 8:34 AM

Post #5 of 7 (2986 views)
Re: [alex5161] command line option -n , -p with multiple files... [In reply to] Can't Post

 
The Explanation for the answers your received has almost nothing to do with -n and everything to do with <>.

All that -n does for you is to create a while loop as we can see in the documentation of -n in perlrun

Quote
-n
causes Perl to assume the following loop around your program, which makes it iterate over filename arguments somewhat like sed -n or awk:
1. LINE:
2. while (<>) {
3. ... # your program goes here
4. }


The details of <> in a while loop are documented in The IO OPERATOR section of perlop


Quote
The null filehandle <> is special: it can be used to emulate the behavior of sed and awk, and any other Unix filter program that takes a list of filenames, doing the same to each line of input from all of them. Input from <> comes either from standard input, or from each file listed on the command line. Here's how it works: the first time <> is evaluated, the @ARGV array is checked, and if it is empty, $ARGV[0] is set to "-" , which when opened gives you standard input. The @ARGV array is then processed as a list of filenames. The loop
1. while (<>) {
2. ... # code for each line
3. }


is equivalent to the following Perl-like pseudo code:
1. unshift(@ARGV, '-') unless @ARGV;
2. while ($ARGV = shift) {
3. open(ARGV, $ARGV);
4. while (<ARGV>) {
5. ... # code for each line
6. }
7. }


except that it isn't so cumbersome to say, and will actually work. It really does shift the @ARGV array and put the current filename into the $ARGV variable. It also uses filehandle ARGV internally. <> is just a synonym for <ARGV> , which is magical. (The pseudo code above doesn't work because it treats <ARGV> as non-magical.)


The variable $ARGV is available to the perl program. Refer to the section of perlvar related to 'Variables related to filehandles'


Quote
$ARGV
Contains the name of the current file when reading from <> .


Note: This variable was not available in very old versions of perl. I have not been able to find where it was added. Clearly, I should have read the current documents more carefully before posting my first reply.Blush
Good Luck,
Bill


alex5161
Novice

Jun 1, 2017, 9:49 AM

Post #6 of 7 (2983 views)
Re: [BillKSmith] command line option -n , -p with multiple files... [In reply to] Can't Post

 Appreciate your effort writing everything.
(BTW, my question, actualy, asked exactly about the '<>' in '-n'-option processing. Maybe, even without the '-n' it still handling @ARGV in the same way, but I have meat it exactly in the '-n' or '-p'; so, that have asked.)


FishMonger
Veteran / Moderator

Jun 1, 2017, 10:00 AM

Post #7 of 7 (2982 views)
Re: [alex5161] command line option -n , -p with multiple files... [In reply to] Can't Post


Code
perl -ne 'print "$ARGV: $. - $_"; close ARGV if eof ARGV' fl[0-3]



(This post was edited by FishMonger on Jun 1, 2017, 10:02 AM)

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives