symgryph has asked for the wisdom of the Perl Monks concerning the following question:

I have a bunch of text files that need some 'post processing' performed on them. Additionally, I want to name the file according to a specific regex contained within each file itself. I have started programming, but can't get filehandles to be turned into an array (which I then use to replace text).

Here is an example of an input file

get system status: Version: FortiGate-60D v5.0,build4459,140410 (GA) Virus-DB: 23.00950(2015-03-02 19:54) Extended DB: 23.00950(2015-03-02 19:53) IPS-DB: 5.00616(2015-02-26 01:09) IPS-ETDB: 0.00000(2001-01-01 00:00) Serial-Number: FGT60D46234234234 Botnet DB: 1.00000(2012-05-28 22:51) BIOS version: 04000023 System Part-Number: P14482-03 Log hard disk: Available Internal Switch mode: interface Hostname: HOSTNAME Operation Mode: NAT Current virtual domain: root Max number of virtual domains: 10 Virtual domains status: 1 in NAT mode, 0 in TP mode Virtual domain configuration: disable FIPS-CC mode: disable Current HA mode: a-p, master Branch point: 271 Release Version Information: GA System time: Tue Mar 3 12:38:43 2015 -------------------------------------------------------------:

Here is what I hope it will output as:

HOSTNAME # get system status Version: FortiGate-60D v5.0,build4459,140410 (GA) Virus-DB: 23.00950(2015-03-02 19:54) Extended DB: 23.00950(2015-03-02 19:53) IPS-DB: 5.00616(2015-02-26 01:09) IPS-ETDB: 0.00000(2001-01-01 00:00) Serial-Number: FGT60D46234234234 Botnet DB: 1.00000(2012-05-28 22:51) BIOS version: 04000023 System Part-Number: P14482-03 Log hard disk: Available Internal Switch mode: interface Hostname: HOSTNAME Operation Mode: NAT Current virtual domain: root Max number of virtual domains: 10 Virtual domains status: 1 in NAT mode, 0 in TP mode Virtual domain configuration: disable FIPS-CC mode: disable Current HA mode: a-p, master Branch point: 271 Release Version Information: GA System time: Tue Mar 3 12:38:43 2015 #HOSTNAME -----------------------------------:

Finally I would like it to rename each file from its original name to the hostname matched by the 'hostname' match within the program.

#!/usr/bin/perl -w open DATA, "*.txt"; @file=<DATA>; while (@file) { if (/Hostname\:\s(\S+)/) { $hostname=$1; print "$hostname\n" } if (/\:$/) { print "# $hostname \n $_"; } }

I can't get the system to even print successfully I get loads of errors. I do know that th regexes are right, and have tested these independently. I also know that I can use a 'rename' function to rename the files, but am not sure how to get the variables to keep state between all the files.

"Two Wheels good, Four wheels bad."

Replies are listed 'Best First'.
Re: Have perl replace a bunch of text in lots of files
by toolic (Bishop) on Mar 03, 2015 at 21:57 UTC
    Please remove the "div" tags from your node.

    One way to create an array of files names is to use glob

    use warnings; use strict; for my $filename (glob '*.txt') { open my $fh, '<', $filename or die "can not open $filename: $!\n"; while (<$fh>) { # your code } close $fh; }
      Sorry for the Blasphemy, don't know what I was thinking.
        Has "use common::sense;" not caught on in the Monastery?

        How is that relevant to what toolic wrote?

        Besides, whether or not common::sense makes sense is subjective, as the module's documentation admits. It doesn't turn on use strict 'refs';!

Re: Have perl replace a bunch of text in lots of files
by cheako (Beadle) on Mar 04, 2015 at 20:21 UTC

    You've not explained what you plan to alter in each file.

    cheako@hades:~$ diff -u <(curl 'http://www.perlmonks.org/?abspart=1;di +splaytype=displaycode;node_id=1118669;part=1') <(curl 'http://www.per +lmonks.org/?abspart=1;displaytype=displaycode;node_id=1118669;part=2' +) --- /dev/fd/63 2015-03-04 14:06:27.032424647 -0600 +++ /dev/fd/62 2015-03-04 14:06:27.032424647 -0600 @@ -1,6 +1,4 @@ - -get system status: - +HOSTNAME # get system status Version: FortiGate-60D v5.0,build4459,140410 (GA) Virus-DB: 23.00950(2015-03-02 19:54) Extended DB: 23.00950(2015-03-02 19:53) @@ -24,4 +22,5 @@ Release Version Information: GA System time: Tue Mar 3 12:38:43 2015 --------------------------------------------------------------: +#HOSTNAME -----------------------------------: +

    As for the simple part: rename
    On UNIX like systems it does not matter if you are working with the file or not, I'm not sure if this was ever fixed in Windows. For portable code you can maintain a hash of files you will rename and process them all at the end.

    As suggested, don't SLURP unless you have too.

Re: Have perl replace a bunch of text in lots of files
by cheako (Beadle) on Mar 05, 2015 at 00:28 UTC
    If you wanted you could get seriously magical.
    # set up to iterate over the *.txt files in the current directory, # editing in place and saving the old file with a .orig extension local $^I = '.orig'; # emulate -i.orig local @ARGV = glob("*.txt"); # initialize list of files my $fileindex=0; my $hostname; while (<>) { $hostname=$1 if (/Hostname:\s(\S+)/); print "# $hostname\n" if (/:$/); print; } continue { if(eof){ close ARGV; rename $ARGV[$fileindex], "${hostname}.txt" if ($hostname); # Careful, this will overwrite files. $fileindex++; $hostname=undef; } }