I'm trying to append hostname in configuration file using sed, because there are multiple hosts that I need to add, so I want to to automate it. I am stuck with the following situation:
Example InputFile :
#######################################################################
#
#Service: System Uptime
#######################################################################
define service{
use generic-service
host_name host1,host2,host3,host4,host5,host6,host7,host8,host9,host10,host11,host12,host13,host14,host15,host16,host17,host18,host19,host20,host21,host22,host23,host24,host25,host26,host27,host28,host29,host30
service_description System Uptime
is_volatile 0
check_period 24x7
contact_groups Test_group
notification_options c,w,r,u
check_command check_nt_uptime
max_check_attempts 3
normal_check_interval 1
retry_check_interval 1
notification_interval 120
notification_period 24x7
}
What am trying to achieve is appending new hosts to "host_name" line, but there are so many occurrences of "host_name" in the file, so to add it for a specific service I have searched for "Service: System Uptime" then in the 7th line from there I search "host_name" and append new hosts.
I have done what I want using sed:
sed '/Service: System Uptime/{N;N;N;N;N;N;N;N;/host_name/s|$|,NewHost|}' input file
Now the problem is when there are multiple hosts in there then the above sed command fails, it breaks the line and appends the host.
Any suggestions on that?
I am not sure I understand your problem and I am unable to reproduce it based on the configuration file snippet you have provided.
Having said that, I believe the following command is roughly equivalent to yours and does not depend on a "number of lines"-based seek.
sed '/Service: System Uptime/,/host_name/{/host_name/s|$|,NewHost|}' input_file
Why are you trying to use sed? This is a job for awk:
awk '/#Service: System Uptime/ {a=1}
a && /host_name/ { a=0; $0 = $0 ", new_host" } 1' input-file
Related
\#Add another new line of text to hosts and send the output to
hosts_update.sh
sed '/localhost/a\
# Gateway
10.0.0.1 it20.it.cs.umb.edu it20
# Addresses for the Windows PCs
10.0.0.240 it21.it.cs.umb.edu it21\
10.0.0.241 it22.it.cs.umb.edu it22\
10.0.0.242 it23.it.cs.umb.edu it23\
10.0.0.243 it24.it.cs.umb.edu it24\
10.0.0.244 it25.it.cs.umb.edu it25\
10.0.0.245 it26.it.cs.umb.edu it26\
10.0.0.246 it27.it.cs.umb.edu it27\
10.0.0.247 it28.it.cs.umb.edu it28\
' hosts > hosts_update.sh
First things first, your initial couple of lines look way off for a shell script. It looks like your hosts_update.sh line should be part of the comments (and the comment shouldn't start with a \ anyway):
# Add another new line of text to hosts and send the output
# to hosts_update.sh
Secondly, you need a \ at the end of each line that you're appending with sed, at the moment you only have it on certain select lines. With that in mind, this script is probably what you wanted:
# Add another new line of text to hosts and send the output
# to hosts_update.sh
sed '/localhost/a\
\
# Gateway\
10.0.0.1 it20.it.cs.umb.edu it20\
\
# Addresses for the Windows PCs\
10.0.0.240 it21.it.cs.umb.edu it21\
10.0.0.241 it22.it.cs.umb.edu it22\
10.0.0.242 it23.it.cs.umb.edu it23\
10.0.0.243 it24.it.cs.umb.edu it24\
10.0.0.244 it25.it.cs.umb.edu it25\
10.0.0.245 it26.it.cs.umb.edu it26\
10.0.0.246 it27.it.cs.umb.edu it27\
10.0.0.247 it28.it.cs.umb.edu it28\
' hosts > hosts_update.sh
What's actually happening in your case (without the \ continuation characters):
sed '/localhost/a\
# Gateway
10.0.0.1 it20.it.cs.umb.edu it20
is that:
you append a single blank line after localhost;
then you have a sed comment line;
then you tell sed to execute . on line number ten.
At that point, sed rightly complains it has no idea what to do with the . command :-)
I'd say, based on experience, an earlier (working) iteration of the script had only the it21-28 lines and someone added (badly) the it20 and comment/blank lines. That's based on the fact only those lines are the errant ones. However, that's just (informed) speculation and doesn't affect the answer.
And, finally, you probably don't want to call the resultant file hosts_update.sh, people will almost certainly think it's a shell script rather than the hosts file it actually is.
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.
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.
Here is an extract from a script showing the variables for the script
PathToPiconPNG="/var/OscamSrvidPicon/picon/19.2E/"
PathToOscamSrvid="/var/OscamSrvidPicon/picon/19.2E/oscam.srvid"
PathToPiconTPL="/var/OscamSrvidPicon/oscam_picons/"
PathToTmp="/tmp/"
I want to run this script numerous times replacing (for example) this line:
PathToPiconPNG="/var/OscamSrvidPicon/picon/19.2E/"
with this lines
PathToPiconPNG="/var/OscamSrvidPicon/picon/28.2E/"
I have tried using sed (I know this example is wrong but you might get what im trying to achieve)
sed 's/{PathToPiconPNG="/var/OscamSrvidPicon/picon/19.2E/"}/{PathToPiconPNG="/var/OscamSrvidPicon/picon/28.2E/"}/g' filename.txt > newfilenam.txt
If that is not possible, is there any way that I can set the variable externally from another script
sed -E 's/picon\/.+\//picon\/28.2E\//' filename.txt > newfilenam.txt
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.