I'm tired to find a solution for sed substitution on /etc/bashrc
I like change the line
PS1="\u#\h NEW [\w]# "
for this
PS1="\u#\h.hostname.com NEW [\w]# "
where hostname.com
HOST=$(hostname)
Try several sustituions, wiht escape \ but nothing.
Also see another question, How do I escape backslashes in a sed script embedded in a bash script but I'm lost.
Usually I use "" for use ${VARIABLE} but don't work, also if use \ for escape
sed -i "s/^PS1.*$/PS1=\"\\u#\\h.${HOST}\ \[\\w\]#\ \"/g" /etc/bashrc
Use \H if you want the complete hostname in your prompt. Then you wouldn't have to worry about this sed substitution.
Change your PS1 to:
PS1="\u#\H NEW [\w]# "
If you want to use sed, the following command should work:
sed 's/\(^.*\h\)\(.*$\)/\1.'"$HOST"'\2/g' /etc/bashrc
After several test, I've got a solution.
HOST=$(hostname); sed -i "s/^PS1.*$/PS1=\"\\\u#\\\h.${HOST}\ \[\\\w\]#\ \"/g" /etc/bashrc
Afert read comment from user dogbane y change to
sed -i "s/^PS1.*$/PS1=\"\\\u#\\\H\ \[\\\w\]#\ \"/g" /etc/bashrc
Thanks...
Related
I want to run a script to search the /etc/bash.bashrc file for the substring
PS1=
and replace the entire line with:
PS1='\[\e[36m\]\h\[\e[m\]\[\e[33m\]#\[\e[m\]\[\e[33m\]\u\[\e[m\]:\[\e[32m\]\W\[\e[m\]>\\$ '
This new line is intended to change the cli prompt.
I have tried and tried sed in a bash script but I couldn't get the regex right.
[Edit] This code now works:
#!/bin/bash
custom_prompt='${debian_chroot:+($debian_chroot)}\[\e[36;40m\]\u\[\e[m\]\[\e[93m\]#\[\e[m\]\[\e[36m\]\h\[\e[m\]:\[\e[92m\]\w\[\e[m\]\[\e[92m\]\\$\[\e[m\]\[\e[93m\]>\[\e[m\]\'
### Setup Bash Prompt
# replace each \ for double \\ in the prompt string
sed_custom_prompt=$(<<<"$custom_prompt" sed 's/\\/\\\\/g')
# add this to /etc/bashrc for global effect
sed -i "s/PS1=.*/PS1=\"$sed_custom_prompt\"/" testrc
The only problem is that it does PS1= " string "
rather than PS1 = ' string ' with back tics.
I need a simple old fashioned non-regex script that finds a string and replaces a line in a file. Regex can find the string but my original statement messed up the substitution.
I don't care if it is perl, awk or bash. I just need something that works.
Instead of writing scripts to replace the existing PS1 jest overwrite it it's much simpler.
echo PS1="This is my prompt" >> /etc/bash.bashrc
This wil append the new PS1 to the end of the file and since this in the end it will overwrite the default PS1 initialization.
You should escape every \ to make sure they aren't lost.
EDIT: The PS1 string should be wrapped with double quotes as well.
$ custom_prompt="\[\e[36m\]\h\[\e[m\]\[\e[33m\]#\[\e[m\]\[\e[33m\]\u\[\e[m\]:\[\e[32m\]\W\[\e[m\]>\\$ "
$ sed_custom_prompt=$(<<<"$custom_prompt" sed 's/\\/\\\\/g')
$ sed -i "s/PS1=.*/PS1=\"$sed_custom_prompt\"/" testrc
$ source testrc
laptop#user:~>$
The following code works on my laptop. The problem was in last \ character in the string of your PS1 variable (I removed it):
#! /bin/bash
custom_prompt='${debian_chroot:+($debian_chroot)}\[\e[36;40m\]\u\[\e[m\]\[\e[93m\]#\[\e[m\]\[\e[36m\]\h\[\e[m\]:\[\e[92m\]\w\[\e[m\]\[\e[92m\]\\$\[\e[m\]\[\e[93m\]>\[\e[m\] '
### Setup Bash Prompt
# replace each \ for double \\ in the prompt string
sed_custom_prompt=$(<<<"$custom_prompt" sed 's/\\/\\\\/g')
# add this to /etc/bashrc for global effect
sed -i "s/PS1=.*/PS1='$sed_custom_prompt'/" testrc
exit 0
p.s. I personally like to add the time to the PS1 so I know how long ago a command is exited. Also, you can immediately time stuff if you add it (\D{%H}:\D{%M}).
Try this:
replace='PS1="\[\e[36m\]\h\[\e[m\]\[\e[33m\]#\[\e[m\]\[\e[33m\]\u\[\e[m\]:\[\e[32m\]\W\[\e[m\]>\\$ "'
perl -i -spe 's/^PS1=.*$/$repl/' -- -repl="$replace" -- /etc/bash.bashrc
Note: Maybe remove the -i (in-place edit) in the first run to check if it works.
I am trying to find and replace a specific text content using the sed command and to run it via a shell script.
Below is the sample script that I am using:
fp=/asd/filename.txt
fd="sed -i -E 's ($2).* $2:$3 g' ${fp}"
eval $fd
and executing the same by passing the arguments:
./test.sh update asd asdfgh
But if the argument string contains $ , it breaks the commands and it is replacing with wrong values, like
./test.sh update asd $apr1$HnIF6bOt$9m3NzAwr.aG1Yp.t.bpIS1.
How can I make sure that the values inside the variables are not expanded because of the $?
Updated
sh file test.sh
set -xv
fp="/asd/filename.txt"
sed -iE "s/(${2//'$'/'\$'}).*/${2//'$'/'\$'}:${3//'$'/'\$'}/g" "$fp"
text file filename.txt
hello:world
Outputs
1)
./test.sh update hello WORLD
sed -iE "s/(${2//'$'/'\$'}).*/${2//'$'/'\$'}:${3//'$'/'\$'}/g" "$fp"
++ sed -iE 's/(hello).*/hello:WORLD/g' /asd/filename.txt
2)
./test.sh update hello '$apr1$hosgaxyv$D0KXp5dCyZ2BUYCS9BmHu1'
sed -iE "s/(${2//'$'/'\$'}).*/${2//'$'/'\$'}:${3//'$'/'\$'}/g" "$fp"
++ sed -iE 's/(hello).*/hello:'\''$'\''apr1'\''$'\''hosgaxyv'\''$'\''D0KXp5dCyZ2BUYCS9BmHu1/g' /asd/filename.txt
In both the case , its not replacing the content
You don't need eval here at all:
fp=/asd/filename.txt
sed -i -E "s/(${2//'$'/'\$'}).*/\1:${3//'$'/'\$'}/g" "$fp"
The whole sed command is in double quotes so variables can expand.
I've replaced the blank as the s separator with / (doesn't really matter in the example).
I've used \1 to reference the first capture group instead of repeating the variable in the substitution.
Most importantly, I've used ${2//'$'/'\$'} instead of $2 (and similar for $3). This escapes every $ sign as \$; this is required because of the double quoting, or the $ get eaten by the shell before sed gets to see them.
When you call your script, you must escape any $ in the input, or the shell tries to expand them as variable names:
./test.sh update asd '$apr1$HnIF6bOt$9m3NzAwr.aG1Yp.t.bpIS1.'
Put the command-line arguments that are filenames in single quotes:
./test.sh update 'asd' '$apr1$HnIF6bOt$9m3NzAwr.aG1Yp.t.bpIS1'
must protect all the script arguments with quotes if having space and special shell char, and escape it if it's a dollar $, and -Ei instead of -iE even better drop it first for test, may add it later if being really sure
I admit i won't understant your regex so let's just get in the gist of solution, no need eval;
fp=/asd/filename.txt
sed -Ei "s/($2).*/$2:$3/g" $fp
./test.sh update asd '\$apr1\$HnIF6bOt\$9m3NzAwr.aG1Yp.t.bpIS1.'
Someone with better experience then me regarding bashscript that could take a look at this code and explain why no string replacements is taking place. If I run the same command (text input instead of variables) in the terminal, then it works.
#!/bin/bash
echo "important to escape every \"/\" character"
read -p "Specify the old string you want to replace? (from) " FROM
read -p "Specify the new string you want to use instead? (to) " TO
cp ../backup/mysql/dump.sql ../backup/mysql/dump.sql.backup.$(date +"%Y-%m-%d-%H-%M-%S") \
&& sed -i 's/$FROM/$TO/g' ../backup/mysql/dump.sql
Use double quotes for variables expansion instead of single quotes: "s/$FROM/$TO/g"
You can even have the cp implicitly within the sed command itself using -i(inplace) option.
sed -i.backup.$(date +"%Y-%m-%d-%H-%M-%S") "s/$FROM/$TO/g" ../backup/mysql/dump.sql
This will create the backup file as well.
I'm trying to automate an install script for New Relic and in my bash file I have the following:
_APPNAME="Test Application"
_OLD=";newrelic.appname = \"PHP Application\""
_NEW="newrelic.appname = \"${_APPNAME}\""
sed -i 's/$_OLD/$_NEW/g' /etc/php.d/newrelic.ini
For some reason that sed command doesn't trigger at all, can anyone see anything wrong with this logic?
Note I have also tried ${_OLD} and ${_NEW} to no avail.
$_OLD and $_NEW are not expanded inside single quotes. '
Use double quotes " instead:
sed -i "s/$_OLD/$_NEW/g" /etc/php.d/newrelic.ini
I often have to modify files such as sysctl.conf, and I'm familiar with using sed to replace existing values.
Is there a way to append the new key/value pair to the file if sed wasn't able to replace it?
For instance, using this example: modify config file using bash script
sed -c -i "s/\($TARGET_KEY *= *\).*/\1$REPLACEMENT_VALUE/" $CONFIG_FILE
How could I add the $TARGET_KEY = $REPLACEMENT_VALUE new line to $CONFIG_FILE using the same sed expression with slight changes?
And on a related topic, how can I force creation of $CONFIG_FILE if it didn't exist?
You can't easily do it all in a single sed call. It's probably simplest to make it two steps:
if grep -q "$TARGET_KEY *= " $CONFIG_FILE; then
sed -c -i "s/\($TARGET_KEY *= *\).*/\1$REPLACEMENT_VALUE/" $CONFIG_FILE
else
echo "$TARGET_KEY = $REPLACEMENT_VALUE" >>$CONFIG_FILE
fi
There are a few things you should probably do to make the above more robust, however:
Your regular expression is not anchored, which means that trying to set 'PORT' will also find/change 'SUPPORT', etc.
It won't match if the config file might have tabs as well as spaces
It fails if the replacement value has slashes in it.
You should always quote parameter expansions like $CONFIG_FILE, in case the file path contains spaces or shell metacharacters.
It's safe in this instance, but potentially confusing to use single backslashes in a double-quoted string when you want a literal backslash. The shell leaves them alone when it doesn't recognize what comes after it as a special sequence, but it would be clearer if you doubled them.
What does -c do on your version of sed? Neither my Linux nor Mac versions support such an option.
So I would do it this way (the ^I's represent literal tab characters, and the ^A's literal control-A characters, entered by for example typing control-V first on the command line):
if grep -q "^[ ^I]*$TARGET_KEY[ ^I]*=" "$CONFIG_FILE"; then
sed -i -e "s^A^\\([ ^I]*$TARGET_KEY[ ^I]*=[ ^I]*\\).*$^A\\1$REPLACEMENT_VALUE^A" "$CONFIG_FILE"
else
echo "$TARGET_KEY = $REPLACEMENT_VALUE" >> "$CONFIG_FILE"
fi
Use below pseudo code:
if (grep -q key); then
sed...
else
echo key=value >> $CONFIG_FILE
fi