So I have the following string in my config.fish, and init.vim:
Fish: eval sh ~/.config/fish/colors/base16-monokai.dark.sh
Vim: colorscheme base16-monokai
Vim: let g:airline_theme='base16_monokai'
And I have the following shell script:
#!/bin/sh
theme=$1
background=$2
if [ -z '$theme' ]; then
echo "Please provide a theme name."
else
if [ -z '$background' ]; then
$background = 'dark'
fi
base16-builder -s $theme -t vim -b $background > ~/.config/nvim/colors/base16-$theme.vim &&
base16-builder -s $theme -t shell -b $background > ~/.config/fish/colors/base16-$theme.$background.sh &&
base16-builder -s $theme -t vim-airline -b $background > ~/.vim/plugged/vim-airline-themes/autoload/airline/themes/base16_$theme.vim
sed -i -e 's/foo/eval sh ~/.config/fish/colors/base16-$theme.$background.sh/g' ~/Developer/dotfiles/config.fish
sed -i -e 's/foo/colorscheme base16-$theme/g' ~/Developer/dotfiles/init.vim
sed -i -e 's/foo/let g:airline_theme='base16_$theme'/g' ~/Developer/dotfiles/init.vim
fi
Basically the idea is the script will generate whichever theme is passed through using this builder.
I have tried referring this documentation but I am not very skilled at regex so if anybody could give me a hand I would appreciate it.
What I need to happen is once the script is generated sed will look for the above strings and replace theme with the newly generated theme ones.
Try this :
sed -i "s|\(eval sh ~/\.config/fish/colors/base16-\)\([^.]*\)\.\([^.]*\)\\(.*\)|\1$theme.$background\4|
" ~/Developer/dotfiles/config.fish
sed -i "s/\(base16\)\([-_]\)\([a-zA-Z]*\)/\1\2$theme/g" ~/Developer/dotfiles/init.vim
Assuming in the second sed command that the theme is an alphanumeric string. If not, you can complete the character range : [a-zA-Z] with additional characters (eg [a-zA-Z0-9]).
You can replace something in sed using this syntax: sed "s#regex#replacement#g". Because you have /s and 's in your strings, it's easiest not to need to escape them.
There are some characters that need to be escaped to make the regexes. . and $ need to be escaped with a \. The $ in the replacement string needs to be escaped too.
If you want to capture a certain part from match, it's easiest to use char classes. For example, eval sh ~/\.config/fish/colors/base16-([^.]+)\.dark\.sh would be the regex to use if you want your replacement to be airline_theme='$1_base16_\$theme'. In that case, the $1 in the replacement is the thing captured in the regex.
[^.]+ will capture everything up to the next .
I hope this helps you to better understand regexes! This should be detailed enough to show you how to write your own.
You need to use double quotes for parameter expansion not single quotes.
You need to escape the single quotes: 'hello'\''world'
I will make one line for you and leave it as an exercise to fix the other lines
sed -i -e 's~\(let g:airline_theme='\''\)[^'\'']*\('\'\)'~base16_'"$theme"~' ~/Developer/dotfiles/init.vim
The first character after the s in the sed expression string is used as the pattern separator, so by putting / first you have specified / as the separator.
Additionally using the single quote tells the shell not to expand any variables, you are going to want to use double quotes instead.
try something like
sed -i -e "s#foo#eval sh ~/.config/fish/colors/base16-$theme.$background.sh#g" ~/Developer/dotfiles/config.fish
as you've now commented that you needed to find the previous theme string instead of foo
sed -i -e "s#eval sh \~/\.config/fish/colors/base16-.*?\..*?\.sh#eval sh ~/.config/fish/colors/base16-$theme.$background.sh#g" ~/Developer/dotfiles/config.fish
Related
I'm pretty new to using sed's regex so I have some environment variables that I need to be placed into a file if the appropriate 'placeholder' is found.
root#devproc-01:~# printenv
PROC_MODCONF=Include "conf.d/modconf.cfg.lua"
PROC_MODULES="lastlog"; "firewall"; "message_logging";
Here are my two defined environment variables, below are my sed commands, these are part of a Docker Compose entrypoint file.
sed -i s/'{$PROC_MODULES}'/$PROC_MODULES/g /etc/procdev/conf.d/modules.cfg.lua
sed -i s/'{$PROC_MODCONF}'/$PROC_MODCONF/g /etc/procdev/proc.cfg.lua
But when this script executes, I get the error seen in the title:
sed: -e expression #1, char 27: unterminated `s' command
I have double checked that my placeholder variables are indeed present and correct within those two files. This only happens with these two replacements, all of my other replacements work fine. :/ Does something need to be escaped?
Thanks!
As requested, a snippet of one of the config files so that you can see how the placeholder variables are displayed:
umask = "027";
Include "conf.d/modules.cfg.lua"
{$PROC_MODCONF}
Include "conf.d/c2s-s2s.cfg.lua"
Both the sed command and the env var contents need escaping.
sed -i "s/{\\\$PROC_MODCONF}/$PROC_MODCONF/g" /etc/procdev/conf.d/modules.cfg.lua
The sed command is in double quotes. That way bash evaluates the env vars in the double quoted string. So the second $PROC_MODCONF will be replaced with its value from the bash environment.
We need to escape the first literal {$PROC_MODCONF} so that bash does not replace it with the value from the environment.
Since the value of $PROC_MODCONF will be placed into the sed command verbatim, that also needs to be escaped.
$ export PROC_MODCONF="Include\\ \"conf.d\/modconf.cfg.lua\""
$ echo $PROC_MODCONF
Include\ "conf.d\/modconf.cfg.lua"
You need to quote the replacement expansions. You need to do that since they contain spaces. $ also needs to be escaped since it's a meta-character.
sed -i s/'{\$PROC_MODULES}'/"$PROC_MODULES"/g /etc/procdev/conf.d/modules.cfg.lua
sed -i s/'{\$PROC_MODCONF}'/"$PROC_MODCONF"/g /etc/procdev/proc.cfg.lua
I might write it with one set of quotes:
sed -i "s/{\\\$PROC_MODULES}/$PROC_MODULES/g" /etc/procdev/conf.d/modules.cfg.lua
sed -i "s/{\\\$PROC_MODCONF}/$PROC_MODCONF/g" /etc/procdev/proc.cfg.lua
I tried to do the following command in bash:
ls -1 | sed s/\(.*\)/"\1"/
which is add double quotes around each output of ls, but the result shows
sed: 1: "s/(.*)/\1/": \1 not defined in the RE
after I add single quotes around the regular expression, I got the right result. the right one is:
ls -1 | sed 's/\(.*\)/"\1"/'
theocratically I do not need the outer quotes right? any one has the same experience?
Single quotes are used to disable shell parsing of various sequences including backslash escapes. If you don't use them, your sequences like \( are passed to sed as (. You may check that by adding echo to the beginning of your command.
Sending the command to echo will show you what sed sees
$ echo sed s/\(.*\)/"\1"/
sed
Hmm, the sed script disappeared altogether. The exposed "*" is forcing the shell to try to match files. Let's disable that:
$ set -f
$ echo sed s/\(.*\)/"\1"/
sed s/(.*)/\1/
The shell ate the quotes and the backslashes. Quoting the sed script:
$ echo sed 's/\(.*\)/"\1"/'
sed s/\(.*\)/"\1"/
That gives the right result, sed will see the script you want to give it. How can we do that without quotes
$ echo sed s/\\\(.\*\\\)/\"\\1\"/
sed s/\(.*\)/"\1"/
And that's ugly.
Having the following in a file:
public $password = 'XYZ';
I'm trying to replace the password's value with a different one, through an automated deployment process from backup files.
I have the regext that will match the string above in a file, but not much compatible with sed
(public\s\$password\s=\s'(.*)'?)
I also tried
sed -i -e "s/public\s\$password\s=\s'(.*)'/private\s\$password\s=\s'jingle'" configuration.php
Any ideas?
Try this:
sed -i -e "s/public\s\$password\s=\s'\(.*\)'/private \$password = 'jingle'/" configuration.php
The problem was that you need to 'escape' the round brackets, and that \s doesn't work in the output pattern. You also had missed the final /.
I am trying to get from user a path as an input.
The user will enter a specific path for specific application:
script.sh /var/log/dbhome_1/md5
I've wanted to convert the number of directory (in that case - 1) to * (asterisk). later on, the script will do some logic on this path.
When i'm trying sed on the input, i'm stuck with the number -
echo "/var/log/dbhome_1/md5" | sed "s/dbhome_*/dbhome_\*/g"
and the input will be -
/var/log/dbhome_*1/md5
I know that i have some problems with the asterisk wildcard and as a char...
maybe regex will help here?
Code for GNU sed:
sed "s#1/#\*/#"
.
$echo "/var/log/dbhome_1/md5" | sed "s#1/#\*/#"
"/var/log/dbhome_*/md5"
Or more general:
sed "s#[0-9]\+/#\*/#"
.
$echo "/var/log/dbhome_1234567890/md5" | sed "s#[0-9]\+/#\*/#"
"/var/log/dbhome_*/md5"
use this instead:
echo "/var/log/dbhome_1/md5" | sed "s/dbhome_[0-9]\+/dbhome_\*/g"
[0-9] is a character class that contains all digits
Thus [0-9]\+ matches one or more digits
If your script is in bash (which I assume when I see the tag, but I also doubt it when I see its name script.sh which seems to have the wrong extension for a bash script), you might as well use pure bash stuff: /var/log/dbhome_1/md5 will very likely be in positional parameter $1, and what you want will be achieved by:
echo "${1//dbhome_+([[:digit:]])/dbhome_*}"
If this seems to fail, it's probably because your extglob shell optional behavior is turned off. In this case, just turn it on with
shopt -s extglob
Demo:
$ shopt -s extglob
$ a=/var/log/dbhome_1234567/md5
$ echo "${a//dbhome_+([[:digit:]])/dbhome_*}"
/var/log/dbhome_*/md5
$
Done!
output=`grep -R -l "${images}" *`
new_output=`regex "slide[0-9]" $output`
Basically $output is a string like this:
slides/_rels/slide9.xml.rels
The number in $output will change. I want to grab "slide9" and put that in a variable. I was hoping new_output would do that but I get a command not found for using regex. Any other options? I'm using a bash shell script.
Well, regex is not a program like grep. ;)
But you can use
grep -Eo "(slide[0-9]+)"
as a simple approach. -o means: show only the matching part, -E means: extended regex (allows more sophisticated patterns).
Reading I want to grab "slide9" and put that in a variable. I assume you want what matches your regexp to be the only thing put in $new_output? If so, then you can change that to:
new_output=`egrep -R -l "${images}" * | sed 's/.*\(slide[0-9]+\).*/\1/'`
Note no setting of output= is required (unless you use that for something else)
If you need $output to use elsewhere then instead use:
output=`grep -R -l "${images}" *`
new_output=`echo ${ouput} | sed 's/.*\(slide[0-9]+\).*/\1/'`
sed's s/// command is similar to perls s// command and has an equivalent in most languages.
Here I'm matching zero or more characters .* before and after your slide[0-9]+ and then remembering (backrefrencing) the result \( ... \) in sed (the brackets may or may not need to be escaped depending on the version of sed). We then replace that whole match (i.e the whole line) with \1 which expands to the first captured result in this case your slide[0-9]+ match.
In these situations using awk is better :
output="`grep -R -l "main" codes`"
echo $output
tout=`echo $output | awk -F. '{for(i=1;i<=NF;i++){if(index($i,"/")>0){n=split($i,ar,"/");print ar[n];}}}'`
echo $tout
This prints the filename without the extension. If you want to grab only slide9 than use the solutions provided by others.
Sample output :
A#A-laptop ~ $ bash try.sh
codes/quicksort_iterative.cpp codes/graham_scan.cpp codes/a.out
quicksort_iterative graham_scan a