Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have a standard text configuration file in Linux (Fedora 20). Most lines should apply all the time, but a few lines need to be "turned on" (uncommented) and "turned off" depending on the machine the file is on. So the file looks like this:
; configuration file
parameter1 = a
parameter2 = b
optparameter1 = z ; only applies to %%machine-1%%
; optparameter1 = x ; only applies to %%machine-2%%
parameter3 = c
; optparameter2 = x ; only applies to %%machine-2%%
optparameter2 = f ; only applies to %%machine-1%%
What I would like to do is run a script that would change the file (or copy the file) altering commenting of the lines based on command line parameters. e.g.
./scriptname -u machine-2 -c machine-1 configurationFileName.conf
This would cause all lines with %%machine-2%% in the end comment to be uncommented (of course, leaving the end comments in tact), and all lines with %%machine-1%% in the end comment to be commented.
Any suggestions on how to do this? Thank you.
The following script will allow you to "turn on" and "turn off" specific lines. In your case, it will "turn off" all lines containing machine-2 and "turn on" lines containing machine-1. The script is as follows:
comm=$1
uncomm=$2
filename=$3
sed -i -e "/$comm/s/^;*/;/" $filename
sed -i -e "/$uncomm/s/^;//" $filename
You run it like this:
./scriptname machine-2 machine-1 configurationFileName.conf
The first sed command adds a semicolon (;) to the lines containing the variable $match, if the line is already commented, it leaves it as is. The second one removes semicolons from the beginning of a line.
Enable config for machine1 (and disable config for machine2) :
$ sed -i -e 's/^;* *\(.*machine-1.*\)/\1/p' \
-e 's/^\(.*machine-2.*\)/;\1/p' configurationFileName.conf
Enable config for machine2 (and disable config for machine1) :
$ sed -i -e 's/^;* *\(.*machine-2.*\)/\1/p' \
-e 's/^\(.*machine-1.*\)/;\1/p' configurationFileName.conf
Be careful because the '-i' sed option will directly modify the "configurationFileName.conf" file.
Related
Sorry if I am not giving you enough info, this is my first time posting here.
I am trying to make this in a bash script.
Downloading...............
"run bash commands and when they are done, replace the "Downloading..." text with the text bellow in the same line aka space."
Downloading............... DONE!
go to next line and show
Installing................
"run bash commands again and when they are done, replace the "Installing..." text with the text bellow in the same line aka space."
Installing................ DONE!
I hope you get what I mean. Thanks in advance.
I've tried:
#/bin/bash
tput sc # save cursor
printf "Something that I made up for this string"
sleep 1
tput rc;tput el # rc = restore cursor, el = erase to end of line
printf "Another message for testing"
sleep 1
tput rc;tput el
printf "Yet another one"
sleep 1
tput rc;tput el
But it doesn't make new lines, it just uses one line to show all text.
I'm assuming you pulled the tput code from somewhere, and I'm guessing that 'somewhere' also explained that tput is being used to overwrite the same line multiple times (as your script actually does).
From your description it doesn't sound like you need to overwrite any lines so using tput is the wrong solution.
If I understand your description correctly you should be able to do everything you want with some (relatively) simple printf commands, eg:
printf "Downloading .... " # no '\n' in the output so cursor remains at end of current line
# run your bash commands here
printf "DONE!\n" # append to end of current line and then add a new line (\n)
printf "Installing .... " # no '\n' in the output so cursor remains at end of current line
# run more bash commands here
printf "DONE!\n" # append to end of the current line and then add a new line (\n)
Keep in mind that if any of your 'bash commands' generate any output then the cursor will be moved (probably to a new line) thus messing up your output. Net result is that you'll need to make sure your 'bash commands' do not generate any output to stdout/stderr (alternatively, make sure all output - stdout/stderr - is redirected to files).
If your requirement is to have the 'bash commands' send output to the terminal then you may need to go back to using tput ... but that's going to depend on exactly how you want the output to appear.
NOTE: If this (above) does not meet your requirement then please update the question with more details.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
as I do some SDR project but also want to watch TV on my computer some time, I need a script to comment blacklist lines in a file in modprobe, when I want to use SDR, and I need to uncomment those lines when I want to watch TV.
So I worked on a script, based on my multiple reading on internet, but unfortunately it doesn't work on my machine.
I hope that you can help me fix it.
Note, individual sed commands did work (with simple quote, as in bash we need double quotes)
#!/bin/bash
# your target file
FILE="/etc/modprobe.d/blacklist-dvb.conf"
# comment target
comment() {
sed -i "s/^/#/g" $FILE # comment all lines
}
# uncomment target
uncomment() {
sed -i "s/^#//g" $FILE
}
I then launch the script as: ./my_script.sh comment (or uncomment, depending on the case)
The main problem is that your script doesn't really do anything. It defines a variable and two functions, and then just exits.
If you want your script to inspect command line arguments and invoke corresponding functions, you'll have to do that manually.
For example:
case "${1:?missing command argument}" in
comment) comment;;
uncomment) uncomment;;
*) echo "$0: bad command: $1" >&2; exit 1;;
esac
Other notes:
Don't use ALL_UPPERCASE for your shell variables. Those are by convention reserved for the system and the shell itself. Better:
file="/etc/modprobe.d/blacklist-dvb.conf"
As a general rule, variable expansions should be quoted ("$file") unless you really know what you're doing.
Your regexes are anchored to the beginning of the string (^). The /g flag is pointless.
In general it's better to use single quotes than double quotes. There are fewer surprises with '...' because everything is taken literally:
sed -i 's/^/#/' "$file"
sed -i 's/^#//' "$file"
OK, as I couldn't get it working in bash, I used python for that, and it does the job perfectly :)
For others who need help, here is my script:
#!/usr/bin/python
import subprocess
import sys
def comment():
subprocess.call(["sed -i 's/^/#/g' /etc/modprobe.d/blacklist-dvb.conf"], shell=True)
def uncomment():
subprocess.call(["sed -i 's/^#//g' /etc/modprobe.d/blacklist-dvb.conf"], shell=True)
# Print
print("Script name ", sys.argv[0])
print("Argument 1 ", sys.argv[1])
argument_1 = sys.argv[1]
if argument_1 == "comment":
print("in comment")
comment()
elif argument_1 =="uncomment":
uncomment()
else:
print("usage = python switcher.py comment")
\#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 am not that good on linux shell script and I need little help.
I want to edit a file via script (finding the line and edit).
The Original line is:
# JVM_OPTS="$JVM_OPTS -Djava.rmi.server.hostname=< hostname >"
I want to uncomment and replaye hostname with 127.0.0.1
JVM_OPTS="$JVM_OPTS -Djava.rmi.server.hostname=127.0.0.1"
You can refer to the set command, change the filename with the name you are working at,
sed -i 's## JVM_OPTS="$JVM_OPTS -Djava.rmi.server.hostname=< hostname >"#JVM_OPTS="$JVM_OPTS -Djava.rmi.server.hostname=127.0.0.1"#' filename
Fine answers, but they don't do anything by way of TEACHING the gentleman how and why it works.
If you were using the mundane text editor, ed, you would use three commands after invoking the command "ed filename":
s/^# //
s/< hostname>/127.0.0.1/
w
So, you can use a pipe to submit those commands directly to ed, specifying "-" as its first argument so that it doesn't bother you by reporting character counts upon reading in and writing out the file:
( echo 's/^# //'; echo 's//127.0.0.1/'; echo w ) | ed - filename
You don't need to echo 'q' also because ed will automatically quit when it runs out of input or encounters "end of file" (you can simulate this on the keyboard by just hitting the CTRL-D key rather than actually typing q ).
Here's one way to do it:
sed -i -e 's/# \(JVM_OPTS=.*=\).*/\1127.0.0.1"/' path/to/file
That is, replace the line with the text captured within the group \(JVM_OPTS=.*=\), so everything from JVM_OPTS= until another = sign, and append 127.0.0.1" to the end.
If there might be other lines in the file starting with # JVM_OPTS=,
then you could make the pattern matching more strict, for example:
sed -i -e 's/# \(JVM_OPTS="$JVM_OPTS -Djava.rmi.server.hostname=\).*/\1127.0.0.1"/' path/to/file
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this question
It's now hard to write one without the capability of freezing the header, like
function viewcsv() {
cat $1 | sed -e "s/,,/, ,/g" | column -s, -t | less -#2 -N -S
}
But is there a utility that allows me to freeze the header, or change the one above to allow it?
[EDIT:] by freezing the header I mean when I scroll up and down with "less", the first line remains there on the top of the screen. Those are usually the header information I want to see even when scrolling down thousands of lines, such as "Date", "Symbol", etc.
I adapted this How to scroll large datafile while keeping header to your wishes:
vim -R -u NONE -N +'map <right> 2zl
map <left> 2zh
map q :qa<CR>
se nu sbo=hor scb nowrap
1sp
winc w
' <(sed -e "s/,,/, ,/g" $1|column -ts,)
-R Readonly mode.
-u NONE all
initializations from files and environment variables are
skipped (they could interfere with the working of e. g. winc w)
-N Not compatible mode (otherwise key names like <right> might not work)
map <right> 2zl to make → scroll horizontally like less -#2
map <left> 2zh to make ← scroll horizontally like less -#2
map q :qa<CR> to make Q quit like less
se nu sbo=hor scb nowrap set options:
'number' - Print the line number in front of each line.
'scrollopt'=hor - Bind horizontal scrolling for 'scrollbind' windows
'scrollbind' - to scroll the header line together with the rest of the data
'nowrap' - lines will not wrap
and only part of long lines will be displayed.
1sp Split current window in two (new window has 1 line, the header)
winc w move cursor to body window
Off the top of my head, you could tailor the less prompt to display the CSV headers instead of the usual prompt.
viewcsv () {
less -PM"$(sed -n 's/,/ /gp;q' "$1")" -M -N -S "$1"
}
(You can still see where you are in the file with = -- I suppose you could replace the short or medium prompt just as well.)
If your data contains percent signs or question marks, they will need to be escaped, as these have a special meaning in the less prompt definition. See the description of the -P option and the section PROMPTS in the less manual for details.
Maybe you could even throw in some terminal escape sequences to get the prompt (or part of it) displayed at the top of the screen, but the trivial solution would superimpose the prompt over data you want to see.
Are you just asking about not changing the first line? (It's not at all clear to me what you mean by 'freezing', but 'not modifying' seems like a reasonable interpretation.)
viewcsv() {
sed -e "1!s/,,/, ,/g" "$1" | column -s, -t | less -#2 -N -S
}
(Removed the redundant keyword 'function' and the UUOC. The relevant addition is the address scope 1! in sed.)
Or perhaps you mean that you want the first line to not go through column:
viewcsv() {
{ sed 1q "$1"; sed -e 1d -e 's/,,/, ,/g' "$1" |
column -s, -t; } | less -#2 -N -S
}