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

Hi Experts, I have a text file which is listing some servers, one server in each line. This file is updated manually, so a result there are cases when at the end some new line characters are also added which are not visible to the human being and the perl code considers them as a server which is actually not the case. I need to know way of removing those new line characters from the end of the file.
server1 server2 server3 <\n> <\n> <\n> <\n>
I want to remove these extra <\n> from the end.
  • Comment on Way to remove the new line characters at the end of the content in a file
  • Download Code

Replies are listed 'Best First'.
Re: Way to remove the new line characters at the end of the content in a file
by roboticus (Chancellor) on Jul 22, 2015 at 01:32 UTC

    shroh:

    Typically for handling files like that, I do this:

    while (<$FH>) { # Remove leading and trailing whitespace from line s/\s+$//; s/^\s+//; # skip blank lines next if /^$/; # do stuff }

    This way, extra whitespace on a server line won't be a problem, nor will a blank line.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      Hi Rob, This is the error when i am using your logic. Variable "$MYFILE" is not imported at outage_nodes_updated.pl line 63. Global symbol "$MYFILE" requires explicit package name at outage_nodes_updated.pl line 63. Execution of outage_nodes_updated.pl aborted due to compilation errors.
      #!C:\Perl\bin\perl.exe use Win32; use IO::Handle; use File::Find; use strict; use warnings; use File::Copy qw(copy); #use Path::Tiny qw/ path /; ###################################################################### +############## #This script is created to put the servers in unplanned outage as part + of the tasks# #that are received to stop the monitoring on the servers #due to some maintenance activity on the servers. # # # require "E:/Temp/inyrohs/omwNodeDetails.pm"; #expect values 'on|off' my ($SEC,$MIN,$HOUR, $DAY, $MON, $YEAR)= (localtime) [0..6]; my $year=$YEAR+1900; my $month=$MON+1; my $day=$DAY; my $date="$year\_$month\_$day"; my $LOG="E:/Temp/inyrohs/maintenanceMode_$date.log"; my $serverlist="E:/Temp/INYROHS/serverlist.txt"; open( MYFILE, "E:/Temp/INYROHS/serverlist.txt") or die "Can't open '$ +serverlist': $!"; my @outagenodes=<MYFILE>; #chomp(@outagenodes); #print "@outagenodes\n"; my $maintMode=$ARGV[0]; chomp($maintMode); open (LOG,">> $LOG") or die "Can't open $LOG file: $!\n"; printf LOG ("\nTime is %02d:%02d:%02d.\nStarting the maintenance mode +process to turn $maintMode outages.\n\n", $HOUR, $MIN, $SEC); #print "$date \n"; #print "starting the process \n"; #print "maintMode: $maintMode:\n"; while (<$MYFILE>){ s/\s+$//; s/^\s+//; next if /^$/; if($maintMode =~ m/on/) { foreach my $NODES (@outagenodes) { my @parts=split /\./, $NODES; my $hostname=$parts[0]; chomp($hostname); my $fqdn = getNodeAttributes($hostname,"PrimaryNodeName"); print "$hostname\n"; #printLog("Node: $NODES, processing...\n"); #print "entered loop \n"; my $cmd="ovownodeutil.cmd -outage_node -unplanned -disable_ +heartbeat -delete_msgs -node_name $fqdn -$maintMode "; print "$cmd\n"; `$cmd`; print "done with command\n"; } } elsif($maintMode=~ m/off/) { foreach my $NODES (@outagenodes) { my @parts=split /\./, $NODES; my $hostname=$parts[0]; chomp($hostname); my $fqdn = getNodeAttributes($hostname,"PrimaryNodeName"); print "$hostname\n"; printLog("Node: $NODES, processing...\n"); printLog("Bringing the server $NODES out of outage.\n"); my $cmd="ovownodeutil.cmd -outage_node -unplanned -disable_ +heartbeat -delete_msgs -node_name $fqdn -$maintMode"; my $cmdresopcmona="ovdeploy -cmd \"ovc -restart opcmona\" - +host $fqdn"; my $cmdresopcle="ovdeploy -cmd \"ovc -restart opcle\" -host + $fqdn"; print "$cmd\n"; `$cmd`; print "$cmdresopcmona\n"; `$cmdresopcmona`; print "$cmdresopcle\n"; `$cmdresopcle`; } } } truncate <MYFILE>,1; sub printLog { my ($logLine) = @_; chomp($logLine); $logLine=$logLine . "\n"; print "$logLine"; print LOG "$logLine"; }

        shroh:

        As the anonymous monk says, $MYFILE and MYFILE are two different things. You're opening your file with:

        open( MYFILE, "E:/Temp/INYROHS/serverlist.txt") or die "Can't open '$s +erverlist': $!";

        Using this method, you have to use MYFILE to read from the file, not $MYFILE. My code uses $FH because current practice in perl is to open files like this:

        open my $MYFILE, '<', "E:/Temp/INYROHS/serverlist.txt" or die "Can't o +pen '$serverlist': $!";

        There are several advantages to this method: It's easier to pass file handles to subroutines when you use lexical variables. Files will automatically close for you when they go out of scope (i.e. you get to the closing '}' of the block containing the definition.

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.

        Why do you think the bareword filehandle MYFILE is related to a variable $MYFILE?
Re: Way to remove the new line characters at the end of the content in a file
by 1nickt (Canon) on Jul 22, 2015 at 01:43 UTC

    Hi shroh. In addition to the above suggestions, see the response to your other question referencing Path::Tiny::lines and its chomp => 1 attribute. This will remove the newline character from the lines as they are pushed onto the array of lines. Then you can just do next if $line =~ /^$/;

    The way forward always starts with a minimal test.
Re: Way to remove the new line characters at the end of the content in a file
by Anonymous Monk on Jul 22, 2015 at 01:25 UTC
Re: Way to remove the new line characters at the end of the content in a file
by hippo (Archbishop) on Jul 22, 2015 at 08:39 UTC
Re: Way to remove the new line characters at the end of the content in a file
by Laurent_R (Canon) on Jul 22, 2015 at 09:31 UTC
    A Perl one-liner to remove the blank lines from your file (changing the original file, please test it first with dummy files):
    perl -ni.bak -e "print $_ if /\w/;" my_file.txt

      Lines containing e.g. a lone } will be removed with that. I'd do this:

      perl -ni.bak -le "print if $_" my_file.txt

      update: Oops! choroba is right below. Heck...

      perl -ni.bak -le "print if length $_" my_file.txt
      perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
        The last line containing 0 and no newline would be removed :-)
        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
        Lines containing e.g. a lone } will be removed with that.
        Oops, that's right, but I based the one-liner on the sample data shown by the OP, i.e. a file with a list of server names, which ought to contain some alphanumerical characters (and/or empty lines), not Perl or C code.

        Perhaps a stricter version:

        perl -ni.bak -e "print $_ unless /^[\n\s]+$/;" my_file.txt
        But even this might also fail on some edge cases, the really right regex really depends on the actual content of the file being processed.
      If there are only blank lines at the end of the file:
      perl -lp00e1 file.txt