functional programming: scan function
on Mar 12, 2009 at 15:49
|
1 reply
|
by metaperl
|
use strict; use warnings;
use Data::Dumper;
=for comment
scanl f q ls = q : case ls of
[] -> []
x:xs -> scanl f (f q x) xs
=cut
sub scanl {
my ($f, $seed, @list)=@_;
my @tail = @list[ 1 .. $#list ] ;
my @rest = scalar @list ? scanl($f, $f->($seed, $list[0]), @tail)
+: ();
($seed, @rest);
}
my @lis = (4,2,4);
sub add { $_[0] + $_[1] }
sub divide { $_[0] / $_[1] }
my @result = scanl \÷, 64, @lis;
warn Dumper(\@result);
@result = scanl \÷, 3, ();
warn Dumper(\@result);
use List::Util 'max';
@result = scanl \&List::Util::max, 5, (1 .. 7) ;
warn Dumper(\@result);
|
One-liner: Inspecting a browser cache with File::MMagic
on Feb 27, 2009 at 21:01
|
0 replies
|
by missingthepoint
|
Browser caches are interesting places. Firefox, in particular, has many files all with intuitive names like 'FA509DE4d01', and no extensions. Fortunately Unix culture has a method for bringing order to this chaos: 'magic' databases, or files containing bytes found in particular types of files. These allow you to guess a file's type based on its contents. Perl provides 'magic' support in the form of File::MMagic, and the following one-liner uses it to print the guessed types of all files in the current directory.
(Update: typo, and removed useless Data::Dumper)
perl -MFile::MMagic -e '$mm=File::MMagic->new; for(glob("*")){$res=$mm
+->checktype_filename($_);print "$_:\t$res\n"}'
|
Win32: Launch and wait for Pageant before resuming
on Feb 03, 2009 at 20:06
|
0 replies
|
by bart
|
I use PuTTY tools from a Perl script, in particular pscp (PuTTY scp), and I use Pageant for automated authentication, so that I don't have to type in my password for every single file to transfer.
But my Pageant uses a password to its vault, too. So Pageant must already be running and ready before I attempt to scp files, or I still have to type in my password, every time, manually.
And that's where this snippet comes in. It tries to start up Pageant, waits till it comes back and/or until you typed in the password and pressed return, and only then resumes.
I use Win32::Process to launch Pageant, and one of 2 things may happen:
Pageant wasn't running and it will pop up a login dialog box asking for the password. And then, after the dialog box closes, the process will continue running in the background, with an icon in the systray. If you Wait for that process to finish, you can wait for a very long time...
Pageant was already running in the systray and the process immediately exits.
So, what does the snippet do?
It reads the parameters to launch Pageant with from a Windows shortcut file (*.lnk file) — You may skip this part.
It launches Pageant using Win32::Process, and it waits for 2 seconds for it to finish. So, in case (2) it'll immediately return, but in case (1) it'll give the program enough time to show its password dialog window.
It uses Win32::GuiTest to see if the password dialog is still up, and polls, and waits until it closes.
use Win32::Process;
use Win32;
use Win32::Shortcut;
my $link = Win32::Shortcut->new;
$link->Load("D:\\Program Files\\Putty\\start pageant.lnk");
$link->Close();
# print "Shortcut to: $link->{Path} $link->{Arguments}\nDirectory:
+ $link->{WorkingDirectory}";
Win32::Process::Create(my $process,
$link->{Path},
qq("$link->{Path}" $link->{Arguments}),
$link->{ShowCmd},
NORMAL_PRIORITY_CLASS,
$link->{WorkingDirectory})
or die Win32::FormatMessage( Win32::GetLastError() );
require Win32::GuiTest; # while we're waiting...
my $result = $process->Wait(2_000); # returns immediately if page
+ant was running
# times out if it just got st
+arted up
while(1) {
my @windows = Win32::GuiTest::FindWindowLike(0, qr/^Pageant:\s
++Enter\s+Passphrase/i)
or last;
sleep 1;
}
|
Programming in Perl without semicolon
on Jan 30, 2009 at 16:50
|
4 replies
|
by buetow
|
I've a few good friends who like Python a lot (yes it is a nice Language, but I like Perl more). One difference is, that you can program in Python without using semicolons. Well, this is possible using the Perl language too, like the following code demonstrates it (it calculates fibonacci numbers, however without use strict). I don't tell, that you will have any benifit by not using a semicolon. But I think this is a funny way of programming in Perl. Enjoy :)
#!/usr/bin/perl
{ $n = shift || die "Usage: perl nosemicolon.pl NUMBER\n" }
sub fib {
if ($_[0] < 2) {
$_[0]
} else {
fib($_[0] - 1) + fib($_[0] - 2)
}
}
{ print "Fibonacci numbers from 0 to $n are as follows:\n" }
for (0 .. $n) {
print "fib($_) = ", fib($_), "\n"
}
print "Thanks for using this software!\n"
|
Obfuscated accessor
on Jan 27, 2009 at 15:16
|
0 replies
|
by bluescreen
|
I was thinking if there any chance to write an accessor in just one line, and I came up with the following code. Of course I wouldn't use in a real project because its unreadable but it might worth sharing. The good thing is just replacing subroutine name creates a new accessor.
sub methodA { $_ = (caller(0))[3];s/.*\://; @_ > 1 ? $_[0]->{$_} = $_[
+1] : $_[0]->{$_} };
|
Vow Triptych
on Dec 30, 2008 at 10:22
|
3 replies
|
by hashED
|
So I'm getting married in October, and I started thinking about wedding vows, and so I wanted to get a better feel for what other people spend most of their wedding vow-ing time talking about. Here's a little script that came out of that effort. It takes a text file full of wedding vows (which you'll have to provide for yourself) and prints the text's triptycs.
#!/usr/bin/perl
my@wordsInOrder;
while (<>) {
foreach ("$_" =~ m/\w+/g) {
push @wordsInOrder, lc($_);
}
}
my$trypHash = {};
for ($i=0;$i < scalar(@wordsInOrder)-2; $i++) {
$trypHash->{$wordsInOrder[$i]." ".$wordsInOrder[$i+1]." ".$wordsIn
+Order[$i+2]} += 1;
}
my$dupeHash = {};
for ($i=0;$i < scalar(@wordsInOrder)-1; $i++) {
$dupeHash->{$wordsInOrder[$i]." ".$wordsInOrder[$i+1]} += 1;
}
my$oneHash = {};
for ($i=0;$i < scalar(@wordsInOrder); $i++) {
$oneHash->{$wordsInOrder[$i]} += 1;
}
foreach my$one (sort {$oneHash->{$b} <=> $oneHash->{$a}} keys %{$oneHa
+sh} ) {
print "$one\n";
foreach my$two (sort {$dupeHash->{$b} <=> $dupeHash->{$a}} keys %{
+$dupeHash} ) {
next unless $two =~ m/^$one/;
print "\t$two\n";
foreach my$three (sort {$trypHash->{$b} <=> $trypHash->{$a}} k
+eys %{$trypHash} ) {
next unless $three =~ m/^$two/;
print "\t\t$three\n";
}
}
}
|
Dump JudyHS
on Dec 29, 2008 at 17:57
|
0 replies
|
by diotalevi
|
This dumps the contents of a Judy::HS/JudyHS(3) array. I had to violate its API to do this. JudyHS is constructed as nested Judy::L/JudyL(3) arrays. The top level encodes the string length. The next level encodes a hashing. Each additional level encodes another 4 or 8 bytes of the input string until no more are needed and it terminates in a C struct which contains the key and value.
The below example loaded Judy::HS with a map from string to line number. It's completely arbitrary and I did it just to demo to myself that I could enumerate the contents of Judy::HS if I needed to.
Judy.h in the Judy C library has a nice, readable description of the structure that's being dumped here.
#!perl
use strict;
use warnings;
use Config '%Config';
use Judy::HS qw( Set );
use Judy::L qw( First Next );
use Judy::Mem qw( Peek Ptr2String2 );
use constant LONGSIZE => 0+$Config{longsize};
# Load $hs with a pile of data.
my $hs;
@ARGV = "$ENV{HOME}/Documents/Political Data/Secretary of state/Statew
+idevoters13102.txt";
while (<>) {
Set( $hs, $_, $. );
}
# Nested printing.
our $P = -1;
sub p { print ' ' x ( 4 * $P ), @_ }
# Loop over JudyL array, each entry contains all strings of length $le
+ngthKey.
my ( undef, $lengthL, $lengthKey ) = First( $hs, 0 );
while ( defined $lengthKey ) {
local $P = 1+$P;
p( "LENGTH: $lengthKey\n" );
# Loop over JudyL array, each entry contains all strings that map to
+ the same $hashKey.
my $hashCount = 0;
my ( undef, $hashL, $hashKey ) = First( $lengthL, 0 );
while ( defined $hashKey ) {
local $P = 1+$P;
p( sprintf "HASH @{[ ++ $hashCount ]}: 0x%x\n", $hashKey );
# Recurse down through JudyL until I find the key/value.
dumpLTree( $hashL );
( undef, $hashL, $hashKey ) = Next( $lengthL, $hashKey );
}
( undef, $lengthL, $lengthKey ) = Next( $hs, $lengthKey );
}
sub dumpLTree {
my ( $l ) = @_;
# Find the stored key/values.
if ( Judy::JLAP_INVALID & $l ) {
$l &= ~Judy::JLAP_INVALID;
local $P = 1+$P;
# Unpack the C struct containing my key value. The value is the fi
+rst
my $value = Peek( $l );
my $str = Ptr2String2( LONGSIZE + $l, $lengthKey );
p( "{Value: $value, String: $str}\n" );
}
else {
# Go deeper.
my ( undef, $innerL, $key ) = First( $l, 0 );
while ( defined $key ) {
local $P = 1+$P;
p( "str: $key\n" );
dumpLTree( $key );
( undef, $innerL, $key ) = Next( $l, $key );
}
}
}
|
Corrector
on Dec 02, 2008 at 10:47
|
2 replies
|
by gok8000
|
#!c:/Perl/bin/Perl.exe
#
# corrector.pl
# changes words inside text files
# placed in the win directory C:\filestochange
# which is supposed to contain text files
#
my $dir_to_process = "C:\\filestochange";
opendir DH, $dir_to_process or die "Cannot open $dir_to_process: $!";
foreach $file (readdir DH) {
unless ($file eq "." || $file eq ".." || $file eq "discarded" || $fi
+le eq "tmp") {
print "in $dir_to_process $file is processed\n";
open (INFILEHANDLE, "C:\\filestochange\\$file") or die "error open
+ing";
open (OUTFILEHANDLE, ">C:\\filestochange\\tempfile8000") or die "e
+rror opening";
while (<INFILEHANDLE>) {
# chomp;
s/this/that/; # substututes this with that
s/one/two/; # substututes one with two
print OUTFILEHANDLE;
}
close INFILEHANDLE;
close OUTFILEHANDLE;
rename "C:\\filestochange\\tempfile8000","C:\\filestochange\\$file
+";
}
}
closedir DH;
print "\nDone (press enter key)\n";
$line = <STDIN>;
|
Commifying sensibly
on Dec 01, 2008 at 09:57
|
2 replies
|
by oko1
|
Recently, I was thinking about that example in the docs where they demonstrate a method for inserting commas into a numerical string. Now, I realize that they're trying to illustrate a specific mechanism with regexes... but that thing is just clumsy and awful and obfuscated for any Perl beginner. So, just for my own entertainment, I decided to see how I'd do it "for real" - i.e., in the best way possible rather than by this contrived method.
Herewith, humbly, I present a couple of options. :)
#!/usr/bin/perl -w
use strict;
die "Usage: ", $0 =~ /([^\/]+)$/, " <numeric_string>\n"
unless @ARGV && $ARGV[0] =~ /^\d+$/;
my ($c, @list);
for (reverse split //, $ARGV[0]){
unshift @list, $c++ % 3 || $c == 1 ? $_ : "$_,";
}
print @list;
# Or, instead of "cheating" with an unquoted list, we could
# aggregate to a string. It's not quite as neat, though. :(
#
# my ($c, $out);
# for (reverse split //, $ARGV[0]){
# $out = $c++ % 3 || $c == 1 ? "$_$out" : "$_,$out";
# }
# print "$out\n";
|
RedHat Linux Security Audit
on Nov 26, 2008 at 15:06
|
2 replies
|
by redleg7
|
|
|
|