Store and read string with newline from Config::Simple config file

Viewed 244

I would like to load a string with newlines from a configuration file. The script I am modifying uses the Config::Simple module.

Here's a MWE:

# file: script.pl

use strict;
use warnings;
use Config::Simple;

# read config file
my $cfg = new Config::Simple('config.cfg');
my %config = $cfg->vars();
# read parameter 'string'
my $var = $config{"string"};

print($var);

This works fine for 'normal' strings in config.cfg:

# file: config.cfg

string: "One Two Three"

Now I want to store a string with newlines in the parameter string. Since Config::Simple requires each parameter to be on a single line (i.e. does not support multi-line parameters), I tried the following

# file: config.cfg

string: "One \nTwo \nThree"

but it seems that Config::Simple strips the \ character, because $var becomes

One nTwo nThree

Is there a good way to do this with Config::Simple?

2 Answers

When you look at the source code for Config::Simple, you see that it calls parse_line from Text::ParseWords which will:

remove all quotes and backslashes that are not themselves backslash-escaped

I can't see a way to modify the behavior of Config::Simple, but one option is to change your config file to backslash the backslashes:

string: "One \\nTwo \\nThree"

This outputs:

One \nTwo \nThree

Interestingly, if you use the param() method instead of the vars() method, you get a different output:

use strict;
use warnings;
use Config::Simple;

my $cfg = new Config::Simple('config.cfg');
my $var = $cfg->param('string');
print "$var\n";

Output:

One 
Two 
Three

I have solved my problem with the help of @toolic's answer:

When I change the config file to include double backslashes, I get the characters \n in $var:

# file: config.cfg

string: "One \\nTwo \\nThree"

The only thing that's left to do is to replace the two characters \n with an actual newline character:

# file: script.pl

use strict;
use warnings;
use Config::Simple;

# read config file
my $cfg = new Config::Simple('config.cfg');
my %config = $cfg->vars();
# read parameter 'string' and regex-replace '\\n' with '\n'
my $var = $config{"string"} =~ s/\\n/\n/gr;

print($var);

This gives me

One
Two
Three

as I wanted.

EDIT: it seems that the replacement is only necessary when using Config::Simple's hash method of accessing the values via .vars(). In the method param() the replacement is actually already implemented within Config::Simple but only there (bug in v4.59, author has been notified). So either use param() or replace \n as described in this answer.

Related