You are not logged in.
I want to learn som simple bash scripting in order to automate various tasks.. Im totally noob, so bear with me
First of all I would like to set configs without using nano.. is there a simple command for this? For example if i want change my hostname in /etc/rc.conf.. how can i print the current vallue and how can i change it`?
i was thinking something like this to get the current value:
# cat /etc/rc.conf | grep HOSTNAME=
which returns HOSTNAME="myhostname"
how can i change this value with one or more commands whitout touching the rest of the file?
Offline
I believe what you need is "sed". It should (to my knowledge) be able to change text inside files.
Here is a link that may help you on your way
http://www.gentoo.org/doc/en/articles/l-sed1.xml
Happy coding
MadEye | Registered Linux user #167944 since 2000-02-28 | Homepage
Offline
i think the sed command would probably be what you are looking for. I would suggest looking at some tutorials to get used to the syntax which can be alittle confusing.
edit: oops, guess i'm a little too late
Last edited by evr (2009-04-17 19:04:08)
Offline
To extract the hostname sed would make a tough time with the optional quotes (I came up with something like sed -n '/HOSTNAME/s/.*="\?\([^"]*\)"\?$/\1/p'). What you can do, because rc.conf is bash source'able is
eval $(grep HOSTNAME /etc/rc.conf)
read -p "The current hostname in rc.conf is $HOSTNAME, enter new name [$HOSTNAME]> " newhost
[ -z "$newhost" ] && exit
sed -i "/HOSTNAME/s/$HOSTNAME/$newhost/" /etc/rc.conf
Offline
I was going to post a simple solution, but Procyon beat me to it (and my script wouldn't have been half this elegant). Endre, aren't you Hungarian by chance?
Last edited by abesto (2009-04-17 19:15:43)
Linux user #476135 || Dotfiles hosted by GitHub
Offline
exelent!
thanks for the help! ill be back after experimenting a bit with sed and the code..
abesto: no im not hungarian.. full blooded norwegian
Offline
Well, welcome to the forums anyway
Also, once you think the thread is 'finished', please mark it [SOLVED] by editing the opening post and setting the subject there.
Linux user #476135 || Dotfiles hosted by GitHub
Offline
thanks abesto been here a while, but inactive for quite some time now, so forgot my username and password.. lol
Procyon's script worked just fine, just what i was thinking.. altough i cant figure out how to get the variable name singeled out..
example:
eval $(grep HOSTNAME /etc/rc.conf)
equals...:
HOSTNAME="whatever"
but if i want to use variables instead of HOSTNAME and /etc/rc.conf
example:
eval $(grep $conf $file)
and say this equals...:
TIMEZONE="Europe/Oslo"
so how do i extract the variable name "TIMEZONE" to use later? how do i get $TIMEZONE in the last example..
this is to avoid bloating the script with many simmilar lines of code..
example:
echo "$TIMEZONE"
hope this makes sense to you.. :-P
Offline
You need variable indirection: ${!var}
So:
$ conf=TIMEZONE
$ file=/etc/rc.conf
$ eval $(grep ^$conf $file)
$ echo ${!conf}
Europe/Oslo
I added a ^ because there is also a timezone string in the comments
Offline
BTW, that method of variable indirection ( ${!var} ) works great in bash, but I don't think it's very portable. You can also use eval to do the same:
$ conf=TIMEZONE
$ file=test.txt
$ cat > test.txt
TIMEZONE="Eastern"
$ eval $(grep ^$conf $file)
$ echo ${!conf}
Eastern
$ eval echo \$$conf
Eastern
Offline
the ${!conf} worked fine! thanks again Procyon..
please explain "portable", im totally noob.. is this important?
could'nt get the "\$$conf" to work.. i dont think the eval works in this specific context.. currently in the title of a 'dialog' box..
Offline
"portable" here means that it won't work in some other shell interpreters. Unless you plan on distributing the script or running it from another shell, this isn't really a problem. I'm not sure which shells do/don't support ${!var} but that's the general idea.
Linux user #476135 || Dotfiles hosted by GitHub
Offline
export HOSTNAME= eval $(grep '^[ ]*HOSTNAME=' /etc/rc.conf)
$HOSTNAME contains your variable
export HOSTNAME to clear any previous definition
ignored white-space at the start of the line, the line must start with HOSTNAME= because you might have another copy commented out
only requires grep and cut so should be pretty portable I'd assume
EDIT: Better?
Last edited by kumyco (2009-04-21 20:14:48)
Offline
@kumyco: Only the last of the dual delimiters works and you miss the case of no quotes at all.
Offline
thanks for all the help.. another question for you guys..
i need a way to check if some_text is in the list_of_text
example
CHOICE="lisa"
NAMES="homer marge lisa bart maggie"
if [ $CHOICE is_anywhere_in_the_list $NAMES ]; then
echo "this is how you do it"
elif [ the same but with other variables ];then
elif [ the same but with other variables ];then
elif [ the same but with other variables ];then
fi
so a loop or something to do this.. been reading on tldp, but cant figure it out :-P
Last edited by endre84 (2009-04-22 20:39:21)
Offline
A slightly naive solution:
CHOICE="lisa"
NAMES="homer marge lisa bart maggie"
if [ "`echo \" $NAMES \" | grep \" $CHOICE \"`" ]; then
echo "this is how you do it"
fi
The extra spaces inside the escaped quotes are to ensure that only a whole word is "matched".
You can also replace the elif's with a loop through a list of "the other variables". Then you'd use the loop variable instead of $CHOICE above.
Linux user #476135 || Dotfiles hosted by GitHub
Offline
CHOICE="lisa"
NAMES="homer marge lisa bart maggie"
if [[ $NAMES =~ $CHOICE ]]; then echo match; fi
Offline
A slightly naive solution:
CHOICE="lisa" NAMES="homer marge lisa bart maggie" if [ "`echo \" $NAMES \" | grep \" $CHOICE \"`" ]; then echo "this is how you do it" fi
The extra spaces inside the escaped quotes are to ensure that only a whole word is "matched".
You can also replace the elif's with a loop through a list of "the other variables". Then you'd use the loop variable instead of $CHOICE above.
grep can check on word-bounderies with \< and \>, or with the -w switch. The -q switch suppresses any messages and exits with exit-code 0 when the first match is found:
if echo "${NAMES}" | grep -qw "${CHOICE}"; then
Nice and readable, should work, but i haven't tested it
EDIT:
CHOICE="lisa"
NAMES="homer marge lisa bart maggie"
if [[ $NAMES =~ $CHOICE ]]; then echo match; fi
This one also matches elisa, ie. no check on word bounderies. You should be carefull with that
Last edited by klixon (2009-04-23 09:40:22)
Stand back, intruder, or i'll blast you out of space! I am Klixon and I don't want any dealings with you human lifeforms. I'm a cyborg!
Offline
I was wondering how to fix that, but \<$CHOICE\> or \b$CHOICE\b doesn't seem to work with =~
Offline
if echo "${NAMES}" | grep -qw "${CHOICE}"; then
Worked like a charm, thanks klixon..
had to change it a littlebit though.. had to remove the {} around the last variable.. and remove the -q in grep to keep it from exit..
if echo "${NAMES}" | grep -w "$CHOICE"; then
Last edited by endre84 (2009-04-23 15:39:46)
Offline
i need more help guys.. a bit complicated this time.. not to good at explaining it :-P hope you understand....
NAMES="homer !marge lisa bart !maggie"
NUMBER="how do i get the number of whole words in $NAMES here?" (5 in this case)
COUNTER="1"
while [ $COUNTER is_less_than_or_equal_to $NUMBER ]
do
PERSON="how do i get the name number $COUNTER from $NAMES" (but without the ! if there is any..) ($COUNTER 2 would set $PERSON to "marge")
TRUE="did the name start with ! ?" (with value "yes" or "no") ( ! = no )
output all this to a file in the following format: (including the \ )
"$COUNTER" "$PERSON" "$TRUE" \
"$COUNTER" "$PERSON" "$TRUE" \
"$COUNTER" "$PERSON" "$TRUE" \
"$COUNTER" "$PERSON" "$TRUE" \
"$COUNTER" "$PERSON" "$TRUE" \
COUNTER=$(( $COUNTER + 1 ))
done
basically i want a file like this
"1" "homer" "yes" \
"2" "marge" "no" \
"3" "lisa" "yes" \
"4" "bart" "yes" \
"5" "maggie" "no" \
then i want to insert this into the script as if it was in there already if possible.. ?? like in the eval $(grep HOSTNAME /etc/rc.conf)....
Last edited by endre84 (2009-04-23 20:30:52)
Offline
final edit:
> cat .bin/testing
#!/bin/bash
names='homer !marge lisa bart !maggie'
count=1
for name in $names; do
if [ "$name" = "$(echo $name | tr -d '!')" ]; then
echo "\"$count\" \"$name\" \"yes\" \\"
else
echo "\"$count\" \"$(echo $name | tr -d '!')\" \"no\" \\"
fi
count=$((count+1))
done
> .bin/testing
"1" "homer" "yes" \
"2" "marge" "no" \
"3" "lisa" "yes" \
"4" "bart" "yes" \
"5" "maggie" "no" \
could be cleaned up a bit
Last edited by brisbin33 (2009-04-23 21:12:28)
//github/
Offline
You can simplify this a bit:
$name | tr -d '!'
like this:
${name#!}
Which means you can do this
if [ ${name} = ${name#!} ]; then
Last edited by klixon (2009-04-23 21:55:07)
Stand back, intruder, or i'll blast you out of space! I am Klixon and I don't want any dealings with you human lifeforms. I'm a cyborg!
Offline
brisbin33: just what i meant, unbelievable that you understood that.. lol
is it possible to insert text from a file directly into the script, so that it works as if it was written in the script and not in a seperate file? this is supposed to be a dialog menu with checkboxes...
so for example:
the script should look like this:
dialog --title "The Simpsons" \
--checklist "The characters in The Simpsons" 25 50 17 \
"1" "homer" "yes" \
"2" "marge" "no" \
"3" "lisa" "yes" \
"4" "bart" "yes" \
"5" "maggie" "no" \
but i need to get the values in the list from a text file, so is there a way to do this?
dialog --title "The Simpsons" \
--checklist "The characters in The Simpsons" 25 50 17 \
THE_COMMAND_TO_INSERT_THE_LIST_FROM_THE_FILE
or is this not possible'`??
Last edited by endre84 (2009-04-24 16:21:30)
Offline
ok this one's gonna be more of a hint than an outright answer.
for name in $(cat $list); do
and if my guess at your overall goal is right, i think you'll run into another problem once you've solved that one...
my recommendation?
echo "dialog..." >> $file
echo "--checklist..." >> $file
for name in...
if...
echo "... yes" >> $file
else...
echo "... no" >> $file
fi
done
cat $file | zenity
exit 0
i hope you can fill in what i've left out...
//github/
Offline