Command to replace string in one file with content of another file - sed

The file /var/cpanel/mainip contains the main IP of my server and nothing else.
The file /etc/csf/csf.blocklists contains a list of firewall blocklists, and part of the file contains a line with an example IP address 1.2.3.4
Normally when installing CSF firewall software on a new server, I will manually replace the example IP address with the server's main IP address. This is required to successfully fetch firewall blocklists from some providers.
To simplify the setup process, I want a command that will replace the example IP address 1.2.3.4 with my main server IP so I don't have to manually do it.
I've tried a sed command, I guess I'm close to the correct command but not quite there yet. Please can you help?
sed -i '/1.2.3.4/ { r /etc/csf/csf.blocklists }' /var/cpanel/mainip
This code is not right because it outputs an error:
sed: -e expression #1, char 0: unmatched `{'
When successful, it should replace 1.2.3.4 with the actual server IP address.

sed -i "s/1\.2\.3\.4/$(</var/cpanel/mainip)/" /etc/csf/csf.blocklists
should do the job.

You only need to specify
sed -i '/1.2.3.4/r /etc/csf/csf.blocklists' /var/cpanel/mainip
In fact even the space is optional ; following will work too
sed -i '/1.2.3.4/r/etc/csf/csf.blocklists' /var/cpanel/mainip
You are simply specifying the pattern /1.2.3.4/ and a command after that
The command could be r for read, w for write, d for delete and a few others
An example of d to delete the entry would be
sed -i '/1.2.3.4/d' /var/cpanel/mainip

Related

Edit a configuration file using bash script

I have a bash script that needs to modify .ssh/config. My goal is to change the HostName value of server1 using sed and I have already managed to do it, but in the file there are more HostName and sed modifies them all. I have tried specifying to sed to stop at the first occurrence but continues to modify them all.
This is the file where I need to change the HostName of server1
Host server1
HostName 172.160.189.196
User admin
Port 353
Host server2
HostName 254.216.34.18
User user
Port 22
This is the command I give:
sed -i '0,/RE/s/HostName .*/HostName 14.208.54.132/' .ssh/config
Try using a sed range:
sed -i '/Host server1/,/HostName/ s/HostName .*/HostName 14.208.54.132/' .ssh/config
This will replace HostName in the range of lines between Host server1 and the first occurrence of HostName, which I think is what you want.
While awk is generally known to work on lines, it actually works with records, by default lines. A record can be defined by a record separator RS. If this variable is empty, it assumes that a record is given by text-blocks separated by one or more empty lines. With this you can do the following:
awk 'BEGIN{RS="";FS=OFS="\n";ORS="\n\n"}
($1~/server1/) {sub(/Hostname[^\n]*\n/,"Hostname 14.208.54.132" OFS)}
1' file
This is not short, but conceptually clean.
Obviously, you have to update the regex to match the hostname such that it is unique. If you also have a hostname server1a, then you will have to make sure that ($1~/server1/) does not match that.
You can use awk like this:
awk '$2=="server1" {f=1} f && /HostName/ {$0=" HostName 14.208.54.132";f=0} 1' file
Host server1
HostName 14.208.54.132
User admin
Port 353
Host server2
HostName 254.216.34.18
User user
Port 22
This might work for you (GNU sed):
sed '/\<server1\>/{:a;n;/HostName/!ba;s/\S\+/14.208.54.132/2}' file
Focus on a line containing server1 then read additional lines until one containing HostName and substitute the second field for the desired result.

Using sed with command-substitution text in the replacement part is not working

I have a CFN with cfn-init to deploy a Apache web server with specified virtual hosts. In the template, I use a AWS::CloudFormation::Init configset to replace local IPs with the Instance's private IP.
config:
packages:...
files:...
services:...
commands:
replacePrivateIP:
cwd: "/etc/httpd/conf"
command: !Sub |
sed -i 's#127.0.0.1#$(curl -s http://169.254.169.254/latest/meta-data/local-ipv4)#g' httpd.conf
The sed command works fine outside the CFN template. But in the CFN-init process, it simply replace "127.0.0.1" with the whole $(curl -s http://...) string.
How can I feed the instance private IP correctly into the httpd.conf file through cfn-init?
The command-substitution syntax $(..) does not work when wrapped in single quotes which is as expected in bash or most other shells as they preserve the literal value present inside. For your substitution to happen, put it inside double-quotes as
sed -i 's#127.0.0.1#'"$(curl -s http://169.254.169.254/latest/meta-data/local-ipv4)"'#g' httpd.conf
Compare the outputs of echo '$(date)' and echo "$(date)" for a simple example of your case.

Sed adds x27 instead single quote

I'm trying to replace a line of text with a single quote using /x27 in my router device to re-configure wifi settings.
The command that I use
sed -i 's/option ssid.*/option ssid \x27test\x27/g' /some/file
The output after I execute above command on my computer(ubuntu 18)
option ssid 'test123'
The output after I execute above command on my router
option ssid x27test123x27
Expected output should be
option ssid 'test123'
So my code is not working properly on the router. How do I achieve this using /x27?
Note: I'm executing this script in a shell script and \x27test\x27 is actually \x27$OPTARG\x27
You can find my full code here
You can double quote Your sed command and then use single quotes inside:
sed -i "s/option ssid.*/option ssid 'test'/g" /some/file
In a comment you said your real code is:
sed -i 's/option ssid.*/option ssid '"'"'"'$OPTARG'"'"'"'/g'
That should be written more correctly and concisely as:
sed -i 's/\(option ssid\).*/\1 '"'$OPTARG'"'/g'
Look:
$ echo 'hi option ssid question' | sed 's/\(option ssid\).*/\1 '"'$RANDOM'"'/'
hi option ssid '5203'
Given your feedback to a different answer it sounds like the version of sed you're running requires a backup file name between the -i and the s/.... Otherwise there's a bug somewhere earlier in your shell script or $OPTARG contains forward slashes or backreferences.

deleting all private IP addresses

Currently I am working on a project where I have a file full of IP addresses I want to delete the IP adddresses that are private (whole range) and using bash to accomplish it. I do make a match of private addresses but unable to delete it.
I have tried:
sed -i '/(192)\.(168)(\.([2][0-5][0-5]|[1][0-9][0-9]|[1-9][0-9]|[0-9])){2}/d' validIPOnly
same for
127.x.x.x,172.16.x.X,10.x.x.x
When using capture groups with sed you either need to escape the ( ) or specify option -E:
$ sed -E -i '/(...)...'
or
$ sed -i '/\(...\)...`
For GNU sed only use the -r option instead of -E.

sed+text on a specific line after an IP

I have the following line in my proftpd log (line 78 to be precise)
Deny from 1.2.3.4
I also have a script which rolls through my logs for people using brute force attacks and then stores their IP (ready for a black listing). What i'm struggling with is inserting (presume with sed) at the end of that specific line - this is what I've got so far:
sed "77i3.4.5.6" /opt/etc/proftpd.conf >> /opt/etc/proftpd.conf
Now one would presume this would work perfectly, however it actually does the following (lines 77 through 78):
3.4.5.6
Deny from 1.2.3.4
I suspect this is due to my dated version of sed, are there any other ways of acheiving the same thing? Also the >> causes the config to be duplicated at the end of the fole (again i'm sure this is a limitation of my version of sed). This is running a homebrew linux kernel on my nas. Sed options below:
root#NAS:~# sed BusyBox v1.7.0
(2009-04-29 19:12:57 JST) multi-call
binary
Usage: sed [-efinr] pattern [files...]
Options:
-e script Add the script to the commands to be executed
-f scriptfile Add script-file contents to the
commands to be executed
-i Edit files in-place
-n Suppress automatic printing of pattern space
-r Use extended regular expression syntax
If no -e or -f is given, the first
non-option argument is taken as the
sed script to interpret. All remaining
arguments are names of input files; if
no input files are specified, then the
standard input is read. Source files
will not be modified unless -i option
is given.
Cheers for your help guys.
This has nothing to do with the version of sed; this is just plain old Doing It Wrong.
sed -i '77s/$/,3.4.5.6/' /opt/etc/proftpd.conf