in reply to Yet another config file editing programme : Tell me how to make it better !

Readability more important than brevity :( Well, I can try...

#!/usr/bin/perl use strict; https://perlmonks.org/?node_id=11136353 use warnings; use Path::Tiny; my $dhcpcdfile = 'fake.353'; # FIXME filename -w $dhcpcdfile or die "cannot write $dhcpcdfile"; my %ip_params = ( interface => "usb0", ip_address => "1.1.1.0", routers => "127.0.0.0", domain_servers => "1.1.1.1" ); %ip_params = ( %ip_params, # add new data to defaults path('inputfile.353')->slurp =~ /^(\w+)=(.*?)\s*$/gm ); # FIXME file +name use Data::Dump 'dd'; dd 'ip_params', \%ip_params; { # block scope for locals local @ARGV = $dhcpcdfile; local $^I = '.bak'; # make backup, do inplace edit my $foundinterface = 0; while( <> ) { if( /^\s*profile\s+static_$ip_params{interface}\b.*\n/m ) # alter th +is section { $foundinterface = 1; warn "found section for $ip_params{interface} at line $.\n"; } elsif( $foundinterface and /static/ ) { s/^\s*static\s+(\w+)=\K.*/$ip_params{$1}/m or warn "failed to chan +ge $1"; warn "set $1 to $ip_params{$1}\n"; } elsif( $foundinterface ) { $foundinterface = 0; warn "ending changes at line $.\n"; } print; } }

The warns and Data::Dump can be removed, of course, making it even more readable :)

  • Comment on Re: Yet another config file editing programme : Tell me how to make it better !
  • Download Code

Replies are listed 'Best First'.
Re^2: Yet another config file editing programme : Tell me how to make it better !
by dazz (Beadle) on Sep 08, 2021 at 03:35 UTC
    Hi
    I have had a go a re-crafting the code by @tybalt89 and other comments. It works but I don't know why. It also spits out errors.

    The errors indicate $1 for the params hash is not initialised on the line:
     s/^\s*static\s+(\w+)=\K.*/$ip_params{$1}/m or warn "failed to change $1";
    I can't see where it is, or should be, initialised.

    If you think I should be able to work this out for myself, you are probably right but my excuse is that I am suffering the effects of concussion from a bicycle crash that nearly killed me in February. Writing some software is exercise for my brain in an attempt to restore something like normal service. As part of my mental gymnastics, I have also been refurbishing a vintage RF signal generator. The diary writeup is here: https://www.eevblog.com/forum/repair/wavetek-2025a-0-2-2-200mghz-rf-sig-gen-repair/
    As with software, I haven't professionally worked on hardware for decades.

    The current code looks like this:
    #!/usr/bin/perl ##### FUNCTION # To read ip settings from a machine generated file and # write those ip settings to the dhcpcd.conf file. # This script is designed to be started by a systemd service.path # The service monitors the mb_ip.cfg file for change. When the file +is changed # the service calls this script. # Updated ip settings are applied after reboot. ##### INPUT # Takes user updates of IP settings saved in to the file /home/mimir/ +mb_ip.cfg # The user setting are range checked by the app before being saved to + file. # The file mb_ip.cfg will only have ip settings that are valid (but n +ot necessarily correct). ##### OUTPUT # Writes the ip settings to the /etc/dhcpcd.conf file. # # Reference: https://www.perlmonks.org/?node_id=11136353 # # Dazz # ver 1.3 # 8 Sept 2021 use strict; use warnings; use Path::Tiny; use Data::Dump; ###### Input file with ip settings my $ip_filename = '/home/mimir/mb_ip.cfg'; # The ip info entered by t +he user into the GUI ###### Output dhcp configuration file # my $dhcpcdfile = '/etc/dhcpcd.conf'; my $dhcpcdfile = 'd.conf'; # TEST ###################################################################### +###################### use constant { FALSE => 0; TRUE => 1; }; # Load the input parameters ip_params from the input file my %ip_params; %ip_params = ( %ip_params, # add new data to defaults, split with "=" path($ip_filename)->slurp =~ /^(\w+)=(.*?)\s*$/gm ); # Print the contents of ip_params. #TEST use Data::Dump 'dd'; dd 'ip_params', \%ip_params; #TEST # Convert 2 lines DNS to 1 line DNS. $ip_params{domain_name_servers} = $ip_params{domain_name_server_1}." " +.$ip_params{domain_name_server_2}; delete($ip_params{domain_name_server_1}); delete($ip_params{domain_name_server_2}); # Print to check the contents ip_params with combined DNS line. + #TEST use Data::Dump 'dd'; dd 'ip_params', \%ip_params; + #TEST { # block scope for locals local @ARGV = $dhcpcdfile; local $^I = '.bak'; # make backup, do inplace edit my $foundinterface = FALSE; while( <> ) { if( /^\s*profile\s+static_$ip_params{interface}\b.*\n/m ) # look for + profile with matching interface name { # format m +atches 'static profile_eth0' $foundinterface = TRUE; warn "found section for $ip_params{interface} at line $.\n"; } elsif( $foundinterface and /static/ ) { warn "ip param key : $ip_params{$0}\n"; #TEST warn "ip param val : $ip_params{$1}\n"; #TEST ***ERROR: $1 not initia +ted. Lines 72 and 73*** s/^\s*static\s+(\w+)=\K.*/$ip_params{$1}/m or warn "failed to chan +ge $1"; # match string before \K Return string after \K # ?? What increments $ip_params through the hash ?? # ?? What stops over-writing of other later sections ?? eg. wlan0 warn "set $1 to $ip_params{$1}\n"; } elsif( $foundinterface ) { $foundinterface = FALSE; warn "ending changes at line $.\n"; } # Output line to dhcpcdfile print; } }
    The input file is this: (slightly different to the previous version)
    #IP Configuration #Mon Sep 06 14:29:34 NZST 2021 routers=192.168.9.91 interface=eth0 domain_name_server_2=8.8.4.9 domain_name_server_1=8.8.8.9 ip_address=192.168.10.9/24
    The abbreviated output file to be updated is this:
    #static domain_name_servers=192.168.1.1 # fallback to static profile on eth0 #interface eth0 #fallback static_eth0 ### Static LAN IP profile for Mimirbox profile static_eth0 static ip_address=1.1.1.1/24 static routers=1.1.1.1 static domain_name_servers=1.1.1.1 2.2.2.2 # Access Point Static interface mimirbox wlan0 interface wlan0 static ip_address=192.130.2.20/24
    If these 3 files are placed in the same directory, the code should run.

    Dazz

      domain_name_servers does not exist in your input file. There is domain_name_server_2 and domain_name_server_1 instead.
      Just a name mismatch.

        Hi

        Thanks for reviewing the code.
        The input file includes 2 lines for DNS that are converted to one line for the dhcpcd.conf output file.
        This happens in the code under the comment  # Convert 2 lines DNS to 1 line DNS


        The error message reports that hash value $1 isn't initialised. This is confirmed by the test print statement immediately prior.
        I think the code should be stepping through the hash but I don't know how that should be done in the context of this code. Is it implied, or should it be explicitly stated?



        Dazz

      What do you think the value of $0 is in the line ?

      warn "ip param key : $ip_params{$0}\n"; #TEST
        Hi
        I added the line:
        warn "ip param key : $ip_params{$0}\n"; #TEST
        and another for debugging to see if hash key $0 and value $1 returned anything. Both printed blank.


        Dazz