Edit conf file linux under specific section - linux

I have a file that I want to change from command line. The thing is that it has sections and in some different sections it has the same values that I need to change.
The file looks like:
...
[DEFAULT]
findtime = 600
maxretry = 3
[ssh]
maxretry = 6
And I want to change only the maxretry under [DEFAULT].
Maybe there is a conifuration command line that searches the section in config file and changes value named X ?
The command I wrote with sed changes all occurences and I want only the first occurence after [DEFAULT]
sudo sed -i "s/\(^maxretry =.*$\)/maxretry = ${NUMBER_OF_RETRIES}/" filename
Appreciate your help.
Thanks

One way using awk:
$ NUMBER_OF_RETRIES=5
$ awk '/^\[DEFAULT\]/{f=1;}f && /^maxretry =/{print "maxretry = "x;f=0;next}1' x=$NUMBER_OF_RETRIES file
First, we search for the DEFAULT section, and once found, set a flag. Search for the line beginning with maxretry, and if flag is set, do the replacement.

You can check a default flag, which tells you if a substitution occurred or not:
awk '!f && /^maxretry =.*$/ {$0="maxretry = 666"; f=1} 1'
Note that this will not write the change in the file, just redirect the output to a new file or do smth similar. This approach is very specific and works only for first occurrence. #Guru's answer is more generic and can work for arbitrary section (e.g. you want to replace the 2nd,3rd occurrence depending on the section). Nevertheless this example is simpler when targeting the first occurrence.

Related

How to read a variable from file, modify and safe it to an other variale

What I want:
There is a file /scripts/backup/config.cfg which contains variables. In my specific case the important ones are:
BACKUPLOCATION=""
ROOTLOCATION="/backup"
Then there is a script /scripts/backup/performBackup.sh
For a specific reason I want a part of the script do the following operations:
read the value of the variable ROOTLOCATION
add a ("/" and) timestamp (Date&Time)
safe the new created value to BACKUPLOCATION (by replacing its current value)
Example
If this is the previous state of the config.cfg:
BACKUPLOCATION="dummy"
ROOTLOCATION="/backup"
After the script ran it should be:
BACKUPLOCATION="/backup/2020-05-02-23-00"
ROOTLOCATION="/backup/"
What I tried
First of all the config file gets "loaded" using
source /scripts/backup/config.cfg
I then tried to use the sed command but the quotes are messing with me. Here is one try (which didn't work):
sed -i 's/BACKUPLOCATION\=.*/BACKUPLOCATION="'$ROOTLOCATION/$(date +%Y-%m-%d-%H-%M)'"/' /scripts/backup/config.cfg
Try this:
source /scripts/backup/config.cfg
sed -i 's|BACKUPLOCATION=.*|BACKUPLOCATION="'"$ROOTLOCATION/$(date +%Y-%m-%d-%H-%M)"'"|' /scripts/backup/config.cfg
The problem with your sed is that you use / as delimiter, which is present in $ROOTLOCATION after expansion, therefore sed fails. I used |, which is usually is not present in filenames. If you ever create a file with |, that sed will fail too! So, "know your data" :)

bash, adding line after specific line

For my actual creating intial server setup script i need to add a line thats saved in a variable after a specific line in a specific file.
I want to add the line:
zend_extension = $phpextensiondir/ioncube_loader_lin_$phpextensionnumber.so
after the following line:
;realpath_cache_ttl = 120
in the following files:
/etc/php/$phpversionnumber/cli/php.ini
/etc/php/$phpversionnumber/cli/fpm.ini
I was looking around, but can't find any what I understand. Actually I'm new to bash scripting.
Can anybody explain? It seems that sed is not the right choice for it?
awk '{print} $0=="old line"{print "new line"}' file

Find entry in .netrc file via bash and delete it if exists

In bash, how do I search for the following string in a file ~/.netrc and delete that line plus the next two lines if found:
machine api.mydomain.com
Example is:
machine api.mydomain.com
user foo
password bar
It should delete all three lines, but I can't match user and password since those are unknown. The only fixed value is machine api.mydomain.com.
Try:
sed -i '' '/^machine api.mydomain.com$/{N;N;d;}' ~/.netrc
When this finds the line machine api.mydomain.com, it reads in two more lines and then deletes them all. Other lines pass through unchanged.
For GNU sed, the argument to -i is optional. For OSX (BSD) sed, the argument is required but is allowed to be empty as shown above.
Let's google it together - sed or awk: delete n lines following a pattern
So, the answer is sed -e '/machine api.mydomain.com/,+2d' ~/.netrc. Add -i flag if changes need to be done in place.

How to delete a particular line which has occurred many times in the file in vim

I want to delete a line: This is an example, which occurs multiple times in a file. How do I go about it.
Thanks,
Alisha
You could do:
:g/This is an example/d
:%s/This is an example\n//gc
% indicates all lines of a file
s indicates pattern to be searched.
g for global replacement
c for confirmation on each replace
If you want to delete the lines containing only the exact match you could:
:g/^This is an example$/d
You can do this using an external command:
:%!grep -v "This is an example"
This filters the entire file through the given command. The grep -v command selects all the lines of the file that do not match the given regular expression.

How can I replace a specific line by line number in a text file?

I have a 2GB text file on my linux box that I'm trying to import into my database.
The problem I'm having is that the script that is processing this rdf file is choking on one line:
mismatched tag at line 25462599, column 2, byte 1455502679:
<link r:resource="http://www.epuron.de/"/>
<link r:resource="http://www.oekoworld.com/"/>
</Topic>
=^
I want to replace the </Topic> with </Line>. I can't do a search/replace on all lines but I do have the line number so I'm hoping theres some easy way to just replace that one line with the new text.
Any ideas/suggestions?
sed -i yourfile.xml -e '25462599s!</Topic>!</Line>!'
sed -i '25462599 s|</Topic>|</Line>|' nameoffile.txt
The tool for editing text files in Unix, is called ed (as opposed to sed, which as the name implies is a stream editor).
ed was once intended as an interactive editor, but it can also easily scripted. The way ed works, is that all commands take an address parameter. The way to address a specific line is just the line number, and the way to change the addressed line(s) is the s command, which takes the same regexp that sed would. So, to change the 42nd line, you would write something like 42s/old/new/.
Here's the entire command:
FILENAME=/path/to/whereever
LINENUMBER=25462599
ed -- "${FILENAME}" <<-HERE
${LINENUMBER}s!</Topic>!</Line>!
w
q
HERE
The advantage of this is that ed is standardized, while the -i flag to sed is a proprietary GNU extension that is not available on a lot of systems.
Use "head" to get the first 25462598 lines and use "tail" to get the remaining lines (starting at 25462601). Though... for a 2GB file this will likely take a while.
Also are you sure the problem is just with that line and not somewhere previous (ie. the error looks like an XML parse error which might mean the actual problem is someplace else).
My shell script:
#!/bin/bash
awk -v line=$1 -v new_content="$2" '{
if (NR == line) {
print new_content;
} else {
print $0;
}
}' $3
Arguments:
first: line number you want change
second: text you want instead original line contents
third: file name
This script prints output to stdout then you need to redirect. Example:
./script.sh 5 "New fifth line text!" file.txt
You can improve it, for example, by taking care that all your arguments has expected values.

Resources