What I need done is to replace a line in a file from perl using a sed command. The issue is the line I need to put into the file has \\ in several places and I have not figured out how to kepp the \\ without perl/sed removing them.
Example is :
system sed "s/^destinaion=.*/destination=Manager {manager hostname\=$NAME,Manager port\=8443} $USER_NAME/" -i /usr/local/example_file.txt;
In the file I get:
destination=Manager {manager hostname=Bill,Manager port=8443} Fred
I need to get in the file :
destination=Manager {manager hostname\=Bill,Manager port\=8443} Fred
This is a properties file for configuration and it needs to be exact.
Using this site I came up with the following solution that works for me:
My command in perl (Just an Example):
$VAR1=$NAME
$VAR2=$USER_NAME
$VAR3='destination=Manager {manager hostname\\\\'
$VAR4='Manager port\\\\=8443} '
system sed 's/^destinaion=.*/$VAR3=$VAR1,$VAR4 $VAR2/' -i
/usr/local/example_file.txt;
Output was :
destination=Manager {manager hostname\=Bill,Manager port\=8443} Fred
This worked as I am passing the same line to 4 different property files depending on the answers to the question and the redhat version. The software I am installing has different property files depending on which redhat version is in use. I have to create the property files by doing one install then I change the property file in my script and do an install on all the servers with a foreach so I can run the script and then watch for errors.
We are currently using two versions so I have had to add if statements in my script to select the correct property files.
As noted in a comment:
It's tricky; you have to work out how many processes are interpreting the string and removing backslashes. To put a single backslash into the output, sed needs to see two consecutive backslashes in the replacement portion of the
s/…/…/
operation. Since you enclose that in double quotes, Perl gets a chance to interpret the backslashes too; that means you need 4 backslashes in the Perl for each one in the output.
Because you're using the 'array' notation for the system
call (except the syntax is wrong — you need commas between the items, and quotes around the plain words), you avoid having a shell interpret the string too.
This works for me on macOS Sierra 10.12.2 and should work with GNU sed
too (renaming the file to data
):
#!/usr/bin/perl
use strict;
use warnings;
my $NAME = "Alexander";
my $USER_NAME = "The Great";
system "sed", "-e", "s/^destinaion=.*/destination=Manager {manager hostname\\\\=$NAME,Manager port\\\\=8443} $USER_NAME/", "-i.bak", "data";
File data
before:
##destinaion=Manager {manager hostname=Bill,Manager port=8443} Fred
destinaion=Manager {manager hostname=Bill,Manager port=8443} Fred
File data
after:
##destinaion=Manager {manager hostname=Bill,Manager port=8443} Fred
destination=Manager {manager hostname\=Alexander,Manager port\=8443} The Great
Here's a variant script that shows how different numbers of backslashes are needed. The example with 8 backslashes in a row has Perl halve the number to 4, the shell halve the number to 2, and sed
interpret the 2 as meaning 1 in the output. When you see 8 backslashes in a row, you can be pretty confident that you're not dealing with something in the best possible way. (In the days of yore, sometimes a troff
file would have 16 backslashes in a row, but not often, and very few people understood why when they were necessary.)
#!/usr/bin/perl
use strict;
use warnings;
my $NAME = "Alexander";
my $USER_NAME = "The Great";
system "sed", "-e", "s/^D1=.*/destination1=Manager {manager hostname\\\\=$NAME,Manager port\\\\=8443} $USER_NAME/", "-i.bak", "data";
system "sed -e \"s/^D2=.*/destination2=Manager {manager hostname\\\\\\\\=$NAME,Manager port\\\\\\\\=8443} $USER_NAME/\" -i.bak data";
system "sed -e 's/^D3=.*/destination3=Manager {manager hostname\\\\=$NAME,Manager port\\\\=8443} $USER_NAME/' -i.bak data";
Here's the initial variant data file:
D1=Manager {manager hostname=Bill,Manager port=8443} Fred
D2=Manager {manager hostname=Bill,Manager port=8443} Fred
D3=Manager {manager hostname=Bill,Manager port=8443} Fred
Here's the result of running the variant script on the variant data file:
destination1=Manager {manager hostname\=Alexander,Manager port\=8443} The Great
destination2=Manager {manager hostname\=Alexander,Manager port\=8443} The Great
destination3=Manager {manager hostname\=Alexander,Manager port\=8443} The Great
If you didn't need $NAME
and $USER_NAME
expanded, there could be another variant with single quotes around the s/…/…/
command in the array notation; it would only need two backslashes, not four.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.