Re: Printing Last Element of a line using perl memory?
by 7stud (Deacon) on Feb 15, 2013 at 01:03 UTC
|
When you are having trouble with regex matching, and you are certain your regex is correct, then it's time to check exactly what's in the string you're matching. One trick is to do this:
say "-->$string<--";
Any trailing whitespace will be apparent:
-->hello world <---
And if there is a newline at the end of the string, you'll see something like this:
-->hello world
<--
Or if you want to reveal every character's ascii code, you can do this:
printf "%vd \n", $string;
--output:--
92.120.50.49.104.101.108.108.111
Edit: the printf applies ord() to the characters, so the printf is not limited to ascii characters.
| [reply] [d/l] [select] |
|
Or if you want to reveal every character in your string's ascii code, you can do this: printf "%vd \n", $string;
Thanks for that. I had no idea it existed.
And (IMO) even better is that is led me to just try: printf "%vx\n", $s;. And whaddayaknow. It worked!
I'll be making much use of that in future.
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
|
my $string = "\x15hello";
printf "%#*vx \n", " ", $string;
--output:--
0x15 0x68 0x65 0x6c 0x6c 0x6f
And the printf() actually reveals every character's ord(), so it's not confined to ascii characters. | [reply] [d/l] |
Re: Printing Last Element of a line using perl memory?
by hippo (Bishop) on Feb 14, 2013 at 23:54 UTC
|
I do not think that regex will work if you have trailling whitespace in your input data (which there appears to be in your example above). To deal with that, try something like
m/(\w+)\W*$/;
instead and see how you get on.
| [reply] [d/l] |
|
| [reply] [d/l] |
Re: Printing Last Element of a line using perl memory?
by pemungkah (Priest) on Feb 15, 2013 at 01:49 UTC
|
A somewhat different way of doing it:
perl -lne 's[\A\s+][]; s[\s+\Z][]; $last=pop [split /\s+/] if $_; END
+{ print $last }' scan.log
- -l auto-chomps
- -n wraps the code in a while(<>){ ... }
- The substitutions remove leading and trailing blanks
- The split extracts the words in the line (whitespace-separated)
- The pop takes the last word
- We save this for each line
- At end of file, we print the current last word, which will be from the last line
| [reply] [d/l] |
|
> The pop takes the last word
Version warning! =)
not with < 5.14
DB<100> $_=join " ",a..z
=> "a b c d e f g h i j k l m n o p q r s t u v w x y z"
DB<101> $x= pop [ split / / ]
;;
Type of arg 1 to pop must be array (not anonymous list ([])) at (eval
+20)[multi_perl5db.pl:644] line 2, at EOF
DB<102> $x= pop @{[ split / / ]} # Workaround
=> "z"
| [reply] [d/l] |
|
| [reply] |
|
|
++ for the END block idea. A further tweak would be to not process data in the main loop, but only the END block. Unfortunately I could not think of a slick way to make $_ available to END from the last loop iteration, so I had to cheat a little to golf your solution. Apparently the autosplit array does remain resident:
perl -nae 'END { print "$F[-1]\n"; }' scan.log
Good examples like yours are weaning me from sed ;-)
| [reply] [d/l] |
|
Ooh, nice! I'll use that one too.
| [reply] |
Re: Printing Last Element of a line using perl memory?
by nvivek (Vicar) on Feb 15, 2013 at 06:26 UTC
|
If we want to print last line of any file, we can use the following code.
use strict;
use warnings;
# open the file using _ to avoid multiple system calls invoked by perl
open _,"filename";
# reading all lines from a file and store it into @lines array
my @lines=<_>;
# printing the last line of a file in @lines by $#lines => last index
+of the array
print @lines[$#lines];
| [reply] [d/l] |
|
That code is bad in so many ways.
# open the file using _ to avoid multiple system calls invoked by perl
open _,"filename";
This is complete nonsense. Using an underscore as the filename makes no difference to the execution, but makes the code harder to understand. Also, you should normally use lexical filehandles. Lastly, there's no error checking on the open.
my @lines=<_>;
This will crash with memory exhaustion if the file is too large
@lines[$#lines];
With warnings enabled, that will give:
Scalar value @lines[$#lines] better written as $lines[$#lines]
But could be even better written as
$lines[-1]
Dave. | [reply] [d/l] [select] |