sed find and replace a string with spaces - regex

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 /.

Related

Linux CentOS sed command with regex issues

I have a txt file under CentOS in which I want to replace any "\t\n" with "\t\t". I tried this:
sed -i -E 's/\t\n/\t\t/g' myfile.txt
but it doesn't work. I don't know if CentOS doesn't support regex in sed.
Any help is appreciated!
p.s.
Input(two lines):
1\t2\t3\t$
4\t5\t6\t$
Output(one line):
1\t2\t\3\t\t4\t5\t6\t\t
In Editplus, the find regex is '\t\n' and the replace is '\t\t'. Then all lines ending with '\t\n' will become one line, and each '\n' is replaced by one additional '\t'.
p.s.
my file is read like this (cat -A myfile.txt)
You may use this perl command to join lines if previous line has a single tab:
perl -i -0777 -pe 's/(\S\t)\n(?!\z)/$1\t/g' excel.log
(?!\z) is a negative lookahead to fail this match for last line of the file.
You need to escape the backslashes.
sed -i -E 's/\\t\\n/\\t\\t/g' myfile.txt

General solutions to replace string regex preceded and followed by '\n'

I have a file in CentOS which looks like following
[root#localhost nn]# cat -A excel.log
real1$
0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I$
real2$
0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I$
real3$
0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I$
real4$
0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I1^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I$
real5$
0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I$
real6$
I would like to replace \nreal[2-6]\n with \t\t\t' and have tried unsuccessfully the following
sed -i 's/\nreal[2-6]\n/\t\t\t/g' file
It seems that sed has difficulty to deal with line break. Any idea to fulfill the regex in CentOS?
Much appreciated!
If you want to consider perl then use:
perl -i -0777 -pe 's/\n(?:51[23]real|real[2-6])(?:\n|\z)/\t\t\t/g' file
If you want to avoid last real\d+ line to be replaced with \t\t\t then use:
perl -i -0777 -pe 's/\n(?:51[23]real|real[2-6])\n(?!\z)/\t\t\t/g' file
(?!\z) is negative lookahead to fail the match when we have line end just ahead of us.
With GNU sed, you need to use the -z option:
sed -i -z 's/\nreal[2-6]\n/\t\t\t/g' file
# ^^
Now, that you also want to handle specific alternations, you need to enable the POSIX ERE syntax, either with -r or -E option:
sed -i -Ez 's/\n(51[23]real|real[2-6])\n/\t\t\t/g' file

Sed matches unwanted extra characters

I want to replace parts of file paths in a configuration file using sed in Cygwin. The file paths are in form of \\\\some\\constant\\path\\2018-03-20_2030.1\\Release\\base\\some_dll.dll (yes, double backslashes in the file) and the beginning part containing date should be replaced.
For matching I've written following regex: \\\\\\\\some\\\\constant\\\\path\\\\[0-9_\.-]* with a character set supposed to match only date, consisting of digits and "-", "_" and "." symbols. This results into following command for replacement: sed 's/\\\\\\\\some\\\\constant\\\\path\\\\[0-9_\.-]*/bla/g' file.txt
The problem is that, after replacement, I get blaRelease\\base\\some_dll.dll instead of bla\\Release\\base\\some_dll.dll as it was successfully replaced using Regexr.
Why does sed behave this way and how can I fix it?
The problem is that the character class [0-9_\.-] is matching backslashes. If you replace the class with [0-9_.-], it will do what you expect.
Note that in a character class, . isn't special and doesn't need quoting. For example, from my Cygwin command line:
$ echo '\.' | sed 's/[\.]/x/g'
xx
$ echo '\.' | sed 's/[.]/x/g'
\x
A simple sed may help you on same.
sed 's/.*Release/bla\\\\Release/' Input_file
In case you want to have backup of Input_file and save the output of it into Input_file itself then following may help you on same.
sed -i.bak 's/.*Release/bla\\\\Release/' Input_file
In another case if you simply want to save output into Input_file itself then following may help you on same too.(difference between above and this one is this one will not create a backup of original Input_file).
sed -i 's/.*Release/bla\\\\Release/' Input_file

Replace Windows filepath in text file by using a Linux sed regular expression

I have a huge number of text files with tag-like syntax. Those files contain patterns like this:
<TAG1=foo><TAG-2=\\10.0.0.1\directory\filename.pdf><TAG3> ...
<TAG4=bar><TAG-6=\\10.0.0.1\directory\filename.tif,other content><TAG5>
I need to replace the first part of those UNC paths with new ones, meaning:
<TAG1=foo><TAG-2=D:\localdirectory\filename.pdf><TAG3> ...
<TAG4=bar><TAG-6=D:\localdirectory\filename.tif,other content><TAG7>
There is a huge number of files to process and so I need to automate this path replacement. So far I tried multiple regex with sed (on Linux) but did not get close to a solution.
#!/bin/bash
# New directory (escaped)
newpath='D:\\localdirectory\\'
# Actual replacement (don't work)
sed -i "s#\(<TAG-2=\)\([^\\]+\.pdf\)#\1${newpath}\2#g" filetoprocess.txt
sed -i "s#\(<TAG-6=\)\([^\\]+\.tif\)#\1${newpath}\2#g" filetoprocess.txt
Any suggestions are welcome
This shell script using sed might work:
#!/bin/bash
oldpath='\\\\10\.0\.0\.1\\directory\\'
newpath='D:\\localdirectory\\'
#sed -i "s#${oldpath}#${newpath}#g" filetoprocess.txt
sed -r -i "s#(<TAG-2=)${oldpath}([^>]+pdf)#\1${newpath}\2#g;
s#(<TAG-6=)${oldpath}([^>]+tif)#\1${newpath}\2#g;
" filetoprocess.txt
In the first line the shell shebang is #! (notice the exclamation mark). And I believe that the second line in your input example should have the TAG-6.
In the paths some care is necessary for the characters that have a special meaning in regular expressions:
you have to escape the . und \ with a backslash
this leads to the funny looking \\\\ (two escaped backslashes)
In the last line the -r option saves a bit of escaping in the argument. Note that I used [^>]+ instead of [^\\]+ to get the path part until the extension.
The [^\\]+ in your sed command would match everything after the = which is not a \ and that is only the D: part.
So your replacement would only match a literal D:.pdf.
But I would suggest trying the other (commented) sed command that just replaces the paths no matter what TAG and fileextension is.
(Backup your files before, since you use -i inplace replacement.)
Finally I came with the following regular expression. This solution can also, manage "/" Unix paths, dollar ($) and hyphens (-) :
sed -i -r 's#(<TAG-2=|TAG-6=)([\/]{2})([0-9.a-zA-Z_$ -]+[\/])+([0-9.a-zA-Z_$ -]+\.[pPtT][dDiI][fF])#\1'"${newpath}"'\\\4#g'

Using sed with regex to find and replace a string

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