Replace end of varying string - regex

I have tried dozens of various sed options but haven't found a combination that works yet. I am trying to turn:
test(3) = var
other(8) = var
test(13) = var
...
into:
test(3) = newvar
other(8) = var
test(13) = newvar
...
The problem I'm encountering is the varying value in the parentheses. I want to edit after the value, to prevent having to catch it and assign it. I tried the following, thinking I could use .* as a wildcard inside the parentheses, but I can't seem to get it to work.
sed -n "s/\(test(.*\)\s+\w+/\1) = newstuff/g" file.txt

You can use this sed command:
sed -i.bak 's/^\([^=]* *= *\).*$/\1newvar/' file
This will match RHS string (from start until = is found) and that is replaced by newvar
If you want to use a shell variable then use double quotes:
NEWVAR="something"
sed -i.bak "s/^\([^=]* *= *\).*$/\1$NEWVAR/" file
UPDATE: To change only lines starting with test:
sed -i.bak "s/^\( *test *[^=]* *= *\).*$/\1$NEWVAR/" file

Related

sed to edit a line on a file

I have a line value I need to update on a file,
export const ADDRESS_ORIGIN = 'chupa-cabra.muz.id';
Im tryging to update with:
sed -i '' 's/ADDRESS_ORIGIN ="[0-9.]*"/ADDRESS_ORIGIN ="'chapuza'"/' constants.js
But the value for
ADDRESS_ORIGIN
Is not updating, I think my REGEX is very wrong, how can I update the value?
Thanks!
There is no way "[0-9.]*" can match 'chupa-cabra.muz.id' but without knowing what the permitted values look like we can only speculate. Perhaps '[^']*' would do what you want, though you need to understand the mechanisms of shell quoting in order to correctly get it through to sed. In this particular case, the simplest by far is to use double quotes around the sed script instead of single:
sed -i '' "s/ADDRESS_ORIGIN = *'[^']*'/ADDRESS_ORIGIN = 'chapuza'/" constants.js
though if you know what you are doing, you could also do it with alternating single and double quotes:
sed -i '' 's/ADDRESS_ORIGIN = *'"'[^']*'"'/ADDRESS_ORIGIN = '"'chapuza'/" constants.js
The basic mechanism here is that adjacent strings will be glued together into one string by the shell. So "a"'b' is a a double-quoted a followed by a single-quoted b. After the shell is done parsing it, you get the string ab. Now for fun, imagine that a is a literal single quote, and b is a literal double quote.
... Or perhaps you only want to replace the first token before the dot? Then '[^.']*\. would match and you'd want to replace with 'chapuza. Or use a back reference '[^.']*\(['.]\) and replace with 'chapuza\1
In the general case, of course, double quotes have different semantics than single, so if your script uses characters which will be mangled by the shell when you switch quotes, you need to add a backslash before them, or switch to the "seesaw quoting" mechanism I described above. But in this particular case, your example script doesn't require any modifications to adapt to double quotes.
I assume you are on macOS because of the way you are using in-place editing; this should work:
sed -E -i '' "s#(ADDRESS_ORIGIN = )'.*'#\1'chapuza'#g"
Result:
export const ADDRESS_ORIGIN = 'chapuza';
Why should it?
You missed the space after the equal sign, and double quotes " will literally match double quotes not single quotes ', and [0-9.]* will match consecutive digits and dots.
An alternative to the bewildering quotes alternating would be use ASCII inside the regex:
sed 's/ADDRESS_ORIGIN *= *\x27[^\x27]*\x27/ADDRESS_ORIGIN = \x27chapuza\x27/'
or
sed 's/\(ADDRESS_ORIGIN\) *= *\x27[^\x27]*\x27/\1 = \x27chapuza\x27/'
Or better still, since there could be double quotes around the value, you can consider both situation by this:
sed -E 's/(ADDRESS_ORIGIN) *= *([\x27\x22])[^\039\034]*\2/\1 = \x27chapuza\x27/'
Where \x27 = \039 = ', \x22 = \034 = " in RegEX.
Like this:
$ echo export const ADDRESS_ORIGIN = \"chupa-cabra.muz.id\"\;|sed -E 's/(ADDRESS_ORIGIN) *= *([\x27\x22])[^\039\034]*\2/\1 = \x27chapuza\x27/'
export const ADDRESS_ORIGIN = 'chapuza';

Sed substitution with Apex character

I'm trying to implement the following substitution
sed -i 's/$config['default_host'] = '';/$config['default_host'] = 'localhost';/' /etc/roundcube/config.inc.php
but it's not working.
What i want to do to is replace $config['default_host'] = ''; with $config['default_host'] = 'localhost'; inside the file /etc/roundcube/config.inc.php
Any ideas?
You should escape the special characters, because sed consider $ as a end of the character in a line
sed "s/\$config\['default_host'\] = '';/\$config['default_host'] = 'localhost';/" fileName
Using Grouping concept
sed "s/\(\$config\['default_host'\] = \)'';/\1'localhost';/" fileName
Output:
$config['default_host'] = 'localhost';

removing {} characters with sed

the problem is, that i cant remove the symbols { and } from strings in HTML files, inside the file the string looks like
Var #footer Set #footer = TransformXML(XML, GetPortfolioItem("Footer_EN_${et.mode}"))
and i need to remove ${et.mode} with the "newmode" text var.
for example
was ("Footer_EN_${et.mode}"))
will be ("Footer_EN_my_current_mode"))
i set a var like the next one
echo -n "choose name: "
read newmode
path=/root/EN
newpath=tmp/EN_$newmode
default_text="${et.mode}"
sed -i "s/\/{et.mode}/\/$newmode/g" *.html
sed -i "s/$default_text/$newmode/g" *.html
but it doesnt work
Try:
sed -i 's/\${et\.mode}/'"$newmode/g" *.html
You need to match the $ character literally, so it needs to be escaped. That should be done inside single quotes. The $newmode variable should be inside double quotes so it gets expanded.

use sed to replace "file={{bla-bla}}" with "file={bla-bla}"

my bibtex file is corrupted in a sense that I need to change
file = {{name:/path/to/file.pdf:application/pdf}},
with file = {name:/path/to/file.pdf:application/pdf}, that is, remove the first pair of curly brackets.
All the strings I am interested start with file = {{.
My first attempt is
echo "file = {{name:/path/to/file.pdf:application/pdf}}," | sed 's/file = {{/file = {/g;s/}}/}/g'
The problem with this one is that it also alters lines like
title = {{ blablabla }} which i don't it want to.
How does one write a REGEX with something like s/file = {{EVERYTHING-IN-BETWEEN/file = {KEEP-WHAT-WAS-THERE}/g ?
p.s. if it's not possible with sed, any other unix commands are welcome.
p.p.s. I am on OS-X, sed here is apparently different to GNU, so some answers below do not work for me, unfortunately.
You can do the following:
sed 's/\(file = \){\({[^}]*}\)}/\1\2/g'
This is probably wrong for your situation, but this will change any double brace to a single brace:
sed 's/\([{}]\)\1/\1/g' <<END
{{
}}
file={{bar-blah}}
{}
}{
END
{
}
file={bar-blah}
{}
}{
The search part \([{}]\)\1 finds a single open or close brace followed by what was just captured. The replacement part is the single captured character.
Assuming both opening and closing braces are on the same line and no other pairs of braces exist on that same line then this should do what you want:
sed '/file *= *{{/{s/{{/{/; s/}}/}/}' file
That's:
/file = {{/ - match lines that have file = {{ on it
{ - start a group of commands
s/{{/{/ - replace {{ with { once
s/}}/}/ - replace }} with } once
} - end a group of commands
If OS X sed cannot handle that command, and this version without the command grouping does not work either:
sed '/file *= *{{/s/}}/}/; /file *= *{{/s/{{/{/'
then this, hopefully, should:
sed -e '/file *= *{{/s/}}/}/' -e '/file *= *{{/s/{{/{/'
or, to steal from glenn jackman's answer a bit:
sed -e '/file *= *{{/s/\([{}]\)\1/\1/g'
huh, GNU sed
echo "file={{bla-bla}}" | sed 's/\(file\s*=\s*\){\s*{\s*\([^}]*\)}\s*}\s*/\1{\2}/'
file={bla-bla}
\s is catching eventual white space characters
assuming that '}' is not inside internal string

How do I replace this text with quotation marks?

I want to replace
$rcmail_config['default_host'] = '';
in /var/lib/roundcube/config/main.inc.php
with
$rcmail_config['default_host'] = 'localhost';
I've tried:
sed -i "s/$rcmail_config['default_host'] = '';/$rcmail_config['default_host'] = 'localhost';/g" /var/lib/roundcube/config/main.inc.php
and
sed -i s/$rcmail_config['default_host'] = '';/$rcmail_config['default_host'] = 'localhost';/g /var/lib/roundcube/config/main.inc.php
But it does not work.
What could I try next?
You need to escape the $ and [ symbols and also you don't need to repeat the same string in the replacement part. Instead of this, you may use capturing groups.
sed -i "s/\(\$rcmail_config\['default_host'\] = \)'';/\1'localhost';/g" file