shell command line to modify a configuration file - shell

I searched this but did not find answer for my problem.
I have a configuration file, which has a line like
server_ip=xxx.xxx.xxx.xxx
This file is in every node in a cluster. The server_ip is just an IP address which sometimes needs to change. I understand that it is easy to change the server_ip to a new ip address if the old ip address is given. But I don't want to keep tracking the old IP address. I just want to force the server_ip address to change to a new value. So the point here is that we don't want to use xxx.xxx.xxx.xxx part to recognize this line. Instead we can only use 'server_ip=' as the locator, and after this line being located, we just set the server_ip to a new value.
Thanks.

GNU sed has an in-place option -i. The command is a simple substitute which replaces each string that matches with the new string. We use double quotes so that we can access the environment variable containing the new address. Because of the double quotes we must escape the $ which denotes the EOL in the match pattern or else the shell would try to see a variable name after it.
I didn't test this, so it's probably wrong, but should get you close. (updated to include OP's fixes.)
newIp=1.2.3.4; sed -i bak "s/server_ip=.*\$/server_ip=$newIp/g" configfile

Use SED!
echo "server_ip=xxx.xxx.xxx.xxx" > file.txt
sed 's/server_ip=.*/server_ip=NEW_IP/g' < file.txt > tmpFile

Related

On microblaze uclinux: put IP address to variable

Yes, this is related to Putting IP Address into bash variable. Is there a better way but nothing of the ideas there work for me on the microblaze uclinux.
I wish to have my ip address of eth0 stored to a shell variable that I can write a script using it. I need alternative ideas how to do this.
ifconfig is available if that helps.
I found that in the file /etc/config/dhcp0.conf the correct ip address is stored, here's the file's content:
1 192.168.10.102
How can I remove the 1 and space without using following commands
grep
sed
cut
this also does not work: echo ${variable:2}
You can use the shell's read built-in:
read num ip </etc/config/dhcp0.conf
$num will contain the number at the beginning of the line, $ip will contain the IP.
Assign ifconfig output of eth0 to array
ifout=($(ifconfig eth0))
Strip off everything before the semicolon of the 6th element of array and assign it to the variable $ethip
ethip=${ifout[6]#*:}

how to edit url string with sed

My Linux repository file contain a link that until now was using http with a port number to point to it repository.
baseurl=http://host.domain.com:123/folder1/folder2
I now need a way to replace that URL to use https with no port or a different port .
I need also the possibility to change the server name for example from host.domain.com to host2.domain.com
So my idea was to use sed to search for the start of the http until the first / that come after the 2 // thus catching whatever in between and will give me the ability to change both server name port or http\s usage.
Im now using this code (im using echo just for the example):
the example shows how in 2 cases where one time i have a link with http and port 123 converted to https and the second time the other way around
and both code i was using the same sed for generic reasons.
WANTED_URL="https://host.domain.com"
echo 'http://host.domain.com:123/folder1/folder2' | sed -i "s|http.*://[^/]*|$WANTED_URL|"
OR
WANTED_URL="http://host.domain.com:123"
echo 'https://host.domain.com/folder1/folder2' | sed -i "s|http.*://[^/]*|$WANTED_URL|"
is that the correct way doing so?
sed regexes are greedy by default. You can tell sed to consume only non-slashes, like this:
echo 'http://host.domain.com:123/folder1/folder2' | sed -e 's|http://[^/]*|https://host.domain.com|'
result:
https://host.domain.com/folder1/folder2
(BTW you don't have to escape slashes because you are using an alternate separating character)
the key is using [^/]* which will match anything but slashes so it stops matching at the first slash (non-greedy).
You used /.*/ and .* can contain slashes, not that you wanted (greedy by default).
Anyway my approach is different because expression does not include the trailing slash so it is not removed from final output.
Assuming it doesn't really matter if you have 1 sed script or 2 and there isn't a good reason to hard-code the URLs:
$ echo 'http://host.domain.com:123/folder1/folder2' |
sed 's|\(:[^:]*\)[^/]*|s\1|'
https://host.domain.com/folder1/folder2
$ port='123'; echo 'https://host.domain.com/folder1/folder2' |
sed 's|s\(://[^/]*\)|\1:'"$port"'|'
http://host.domain.com:123/folder1/folder2
If that isn't what you need then edit your question to clarify your requirements and in particular explain why:
You want to use hard-coded URLs, and
You need 1 script to do both transformations.
and provide concise, testable sample input and expected output that demonstrates those needs (i.e. cases where the above doesn't work).
wrt what you had:
WANTED_URL="https://host.domain.com"
echo 'http://host.domain.com:123/folder1/folder2' | sed -i "s|http.*://[^/]*|$WANTED_URL|"
The main issues are:
Don't use all-upper-case for non-exported shell variable names to avoid clashes with exported variables and to avoid obfuscating your code (this convention has been around for 40 years so people expect all upper case variables to be exported).
Never enclose any script in double quotes as it exposes the whole script to the shell for interpretation before the command you want to execute even sees it. Instead just open up the single quotes around the smallest script segment possible when necessary, i.e. to expand $y in a script use cmd 'x'"$y"'z' not cmd "x${y}z" because the latter will fail cryptically and dangerously given various input, script text, environment settings and/or the contents of the directory you run it from.
The -i option for sed is to edit a file in-place so you can't use it on an incoming pipe because you can't edit a pipe in-place.
When you let a shell variable expand to become part of a script, you have to take care about the possible characters it contains and how they'll be interpreted by the command given the context the variable expands into. If you let a whole URL expand into the replacement section of a sed script then you have to be careful to first escape any potential backreference characters or script delimiters. See Is it possible to escape regex metacharacters reliably with sed. If you just let the port number expand then you don't have to deal with any of that.

Edit conf file without get in the file [duplicate]

This question already has answers here:
Editing/Replacing content in multiple files in Unix AIX without opening it
(2 answers)
Closed 6 years ago.
I wonder know if there is a way to edit a conf file without getting in the file and changing the lines?
In my case, I need to edit zabbix-agent conf file (located in /etc/zabbix/zabbix_agentd.conf) and there are some parameters in the file that I need to change, such as Server Name, DebugLevel, and others.
Normally I edit the file using vim and change the lines, but my idea is to edit the file directly from bash, but I don`t know if this is possible.
For example, if I need to change the parameter DebugLevel, at bash I would run:
# /etc/zabbix/zabbix_agentd.conf.DebugLevel=3
This actually doesn`t works, but I would like something like this for my problem...
Does anyone knows??
I tested what David said, but it didn`t solved my problem... There are some lines in the file that is commented and I need to uncomment them, and there are some lines that I just need to change.
For example, the line above:
# DebugLevel=3
I need to change to:
DebugLevel=3
And this line:
Server=127.0.0.1
I need to change for the IP of zabbix server name, like this:
Server=172.217.28.142
Is there any other way?
If I understand your question correctly, then you want sed -i (the -i option allows sed to edit the file in place, and -i.bak will do the same but create a backup of the original file with the .bak extension)
To change DebugLevel=3 to DebugLevel=4 in file /etc/zabbix/zabbix_agentd.conf, you can do:
# sed -i.bak "/DebugLevel/s/[0-9][0-9]*$/4/" /etc/zabbix/zabbix_agentd.conf
If I misinterpreted your question, please let me know.
To Change Values at the End
Example Input File
$ cat file.txt
DebugLevel=3
Example Use
$ sed -i "/DebugLevel/s/[0-9][0-9]*$/4/" file.txt
$ cat file.txt
DebugLevel=4
To Remove Comments
You can do virtually the same thing to uncomment the parameters of interest, for example:
# sed -i.bak "/DebugLevel/s/^#//" /etc/zabbix/zabbix_agentd.conf
In each case, sed is searching for the label in the first set of forward slashes /.../, next the substitute command is called s and then the expression between the next set of forward slashes, e.g. /^#/ (^ match at the beginning), if matched, is replaced by what follows in the next set // (nothing in the remove comment case).
You will need to adjust the values as required to match each parameter you need to find and replace. Let me know if you have further problems and exactly what the problem is.

How can I replace a word at a specific line in a file in unix

I've researched other questions on here, but haven't really found one that works for me. I'm trying to select a specific line from a file and replace a string on that line with another string. So I have a file named my_course. I'm trying to modify a line in my_course that starts with "123". on that line I want to replace the string "0," with "1,". Help?
One possibility would be to use sed:
sed '/^123/ s/0/1/' my_course
In the first /../ part you just have to specify the pattern you are looking for ^123 for a line starting with 123.
In the s/from/to/ part you have specify the substitution to be performed.
Note that by default after substitution the file will be written to stdout. You might want to:
redirect the output using ... > my_new_course
perform the substitution "in place" using the -e switch to sed
If you are using the destructive in place variant you might want to use -iEXTENSION in addition to keep a copy with the given EXTENSION of the original version in case something goes wrong.
EDIT:
To match the desired lined with a prefix stored in a variable you have to enclose the sed script with double quotes " as using single qoutes ' will prevent variable expansion:
sed "/^$input/ s/0/1/" my_course
Have you tried this:
sed -e '[line]s/old_string/new_string/' my_course
PS: the [ ] shouldn't be used, is there just to make it clear that you should put the number right before the "s".
Cheers!
In fact, the -e in this case is not necessary, I can write just
sed '<line number>s/<old string>/<new string>/' my_course
This is what worked for me on Fedora 36, GNU bash, version 5.2.15(1)-release (x86_64-redhat-linux-gnu):
sed -i '1129s/additional/extra/' en-US/Design.xml
I know you said you couldn't use line numbers; I don't know how to address that part, but this replaced "additional" with "extra" on line 1129 of that file.

Bash-script, sed with two variables doesn't work

I'm writing a script which change IP address every once in a while but for some reason I just can't get this working
sed "s/$curLine/$nextLine/" </etc/network/interfaces>/etc/network/interfaces.new, even if I change the end /g, I will always get "sed unterminated `s' command"
Here is my variables $curLine and $nextLine:
#Find current ip from /etc/network/interfaces
curLine=$(sed -n "/address/p" /etc/network/interfaces)
#Find location of current ip in ips.txt.
newLine=$(sed -n "/$curLine/=" ips.txt)
#Check and set next ip
nextIP=$(($newLine+1))
nextLine=$(sed -n "$nextIP,/address/p" ./ips.txt)
for some reason $nextLine also gives me two ips I don't know why because at the beginning ot worked just fine.
and in the end this is the line which doesn't work as it should.
"s/$curLine/$nextLine/" </etc/network/interfaces>/etc/network/interfaces.new
error message "sed unterminated `s' command". If I replace $nextline with text like "address xxx.xxx.xxx.xx it works just fine.
I have read so many topics where solution was use double quotes but I don't know why it doesn't work with me. I also have a book where's an example which is basically just same what I'm doing but again it doesn't work when I try use it.
Thanks !
The syntax for arithmetic has no extra sigil:
NUM=1
OTHERNUM=$((NUM + 1))
# ^^^^^^^^^^^^
In other words, say nextIP=$((newLine+1)).
Problem solved. I just changed
nextLine=$(sed -n "$nextIP,/address/p" ./ips.txt)
to search range of lines instead of specific line with a pattern.
nextLine=$(sed -n "$nextIP,/$nextIP" ./ips.txt)

Resources