I want to use sed for replacing multiple files from bash script.
When I call it from bash I get below error
DEBUG FLOW:-
FILELIST='/tmp/components/ab.sql /tmp/b.sql'
+ SUBSTITUTE_STRING=abc
+ sed -i.bak -e s/abc/xyz/g '/tmp/components/ab.sql /tmp/b.sql': No such file or directory
however when I used this command directly on terminal it executes successfully
sed -i.bak -e s/abc/xyz/g /tmp/components/ab.sql /tmp/b.sql
The difference from terminal and script is of quotes around the file.
I have tried defining File list variable without quotes as well
kindly suggest
Instead of saying:
FILELIST='/tmp/components/ab.sql /tmp/b.sql'
make it an array by saying:
FILELIST=(/tmp/components/ab.sql /tmp/b.sql)
and while invoking say:
sed -i.bak -e "s/abc/xyz/g" "${FILELIST[#]}"
If you look at the debug flow, it'd be evident that the shell parses the filenames as a single token ('/tmp/components/ab.sql /tmp/b.sql') which causes the No such file or directory error.
Related
I cannot for the life of me figure this out.
I have a sed command being executed here (it's an M1 Mac, which I know has a different version of sed than GNU sed, which could be the problem? But i need the command to act the same on Linux/Windows/Mac:
firstString="SQLITE_KEY=\"?.*\"?[^\w\d]"
secondString="SQLITE_KEY=\"?${SQLITE_KEY_GENERATED}\"?"
sed -i '' -r "/SQLITE_KEY/ s/${firstString}/${secondString}/" .env
I have a set of environment variables in another file, and these are injected into the .env file:
SQLITE_KEY=zCokzf3aVzS0T7cH3mJiyrqUBK5YpETwqVf4tg==
However when I run it, I get an error like this.
sed: 1: "/SQLITE_KEY/ s/SQLITE_K ...": bad flag in substitute command: 't'
The goal here is to take the environment variables from the source file, and inject them into the .env file where SQLITE_KEY is. The "bad flag" warning changes letters every time, so I'm suspecting it's something to do with the formatting of the password.
What am I doing wrong?
You have a syntax conflict involving double-quotes (").
secondString has escaped '"'.
Those are then interpreted by the shell command after the variable substitution for sed.
So ... you need to replace the outside double-quotes by single-quotes on the sed, in this way:
eval sed -i \'\' -r \'/SQLITE_KEY/ s/${firstString}/${secondString}/\' .env
This way, the double-quotes will be correctly carried thru into the .env file.
I am trying to write a shell script to find a replace this line of code on Ubuntu 14.04.
//Code before script runs
/*define('FS_METHOD','direct');*/
//Code after script runs
define('FS_METHOD','direct');
sudo sed -i "s#/*define('FS_METHOD','direct');*/#define('FS_METHOD,'direct');#g" /home/example/example.txt
After running this line of code I do not get any errors, but it does not remove the /* */ I believe this is because of the single quotes. I have tried escaping them with a backslash but it doesn't work either. Anyone have any idea how to get this to work?
No, the problem is that * is an RE metacharcter so you need to escape it to have it treated literally:
$ sed "s#/\*define('FS_METHOD','direct');\*/#define('FS_METHOD,'direct');#g" file
define('FS_METHOD,'direct');
or more concisely:
$ sed "s#/\*\(define('FS_METHOD','direct');\)\*/#\1#" file
define('FS_METHOD','direct');
I'm implementing a template renderer in shell script. The template variables are represented in a template by #VAR_NAME# and their values are defined in a separate shell script.
Sample code:
# template variables values
CONTACT_EMAIL="myemail"
CONTACT_NAME="myname"
VARS="CONTACT_EMAIL CONTACT_NAME"
TEMPLATE_FILEPATH="mytemplate.txt"
# template renderer
set -x
SEDARGS=
for VAR in $VARS; do
SEDARGS+=" -e \"s,#$VAR#,${!VAR},\""
done
sed -r $SEDARGS $TEMPLATE_FILEPATH
sed command executed by shell and printed by it because of "set -x":
+ sed -r -e '"s,#CONTACT_EMAIL#,myemail,"' -e '"s,#CONTACT_NAME#,myname,"' mytemplate.txt
sed output:
sed: -e expression #1, char 1: unknown command: `"'
I know the single quotes around each sed expression are causing this non-intuitive error message, but I do not know why they are added.
What is wrong?
You have embedded quotes inside your SEDARGS variable. These are NOT removed when the command is executed. To remove them, you need to call the interpreter again, which you can do using eval. For example:
eval sed -r $SEDARGS $TEMPLATE_FILEPATH
You may need to play around that some more (adding quotes, etc.).
The single quotes aren't part of the actual arguments. They get added by your shell for the output caused by set -x only.
Why would the shell do that? So that you can use that output to re-run exactly what was executed during the script execution. As you correctly noticed, they are needed to protect the " that came from SEDARGS content (i.e., the inner ones, in your script escaped as \").
I have written a bash script which calls a sed command (amongst other things) on a file to complete a find/replace of 2 different strings.
The trouble is, after running the script, I check the files and nothing has been updated. However, if I run the commands that are being produced (I echo them as output anyway) then they work.
For example, inside the script I have:
echo "/usr/local/bin/sed -i -e 's/${String1}/${String1R}/g;s/\/${String2}\//\/${String2R}\//g' ${ROOT_DIR}/data/file.sql"
/usr/local/bin/sed -i -e 's/${String1}/${String1R}/g;s/\/${String2}\//\/${TString2R}\//g' ${ROOT_DIR}/data/file.sql
Running the script does not change file.sql; however, if I run the command that is printed to console e.g. /usr/local/bin/sed -i -e 's/file_name1/file_name2/g;s//path_substring1///path_substring2//g' /path/to/file/file.sql it works perfectly!
Use double quotes instead of single quotes. Single quotes would prevent variable expansion.
/usr/local/bin/sed -i -e "s/${String1}/${String1R}/g;s/\/${String2}\//\/${TString2R}\//g" ${ROOT_DIR}/data/file.sql
Moreover, it seems that your variables are path strings which might contain forward slashes, i.e. /. In that event use a different separator:
"s|${String1}|${String1R}|g"
Using a different separator would obviate the need of escaping / in the pattern and replacement.
I believe this may be a simple question, but I've looked everywhere and tried some workarounds, but I still haven't solved the problem.
Problem description:
I have to replace a character inside a file and I can do it easily using the command line:
sed -e 's/pattern1/pattern2/g' full_path_to_file/file
But when I use the same line inside a bash script I can't seem to be able to replace it, and I don't get an error message, just the file contents without the substitution.
#!/bin/sh
VAR1="patter1"
VAR2="patter2"
VAR3="full_path_to_file"
sed -e 's/${VAR1}/${VAR2}/g' ${VAR3}
Any help would be appreciated.
Thank you very much for your time.
Try
sed -e "s/${VAR1}/${VAR2}/g" ${VAR3}
Bash reference says:
The characters ‘$’ and ‘`’ retain their special meaning within double quotes
Thus it will be able to resolve your variables
I use a script like yours... and mine works as well!
#!/bin/sh
var1='pattern1'
var2='pattern2'
sed -i "s&$var1&$var2&g" *.html
See that, mine use "-i"... and the seperator character "&" I use is different as yours.
The separator character "&" can be used any other character that DOES NOT HAVE AT PATTERN.
You can use:
sed -i "s#$var1#$var2#g" *.html
sed -i "s#$var1#$var2#g" *.html
...
If my pattern is: "test#email.com" of course you must use a seperator different like "#", "%"... ok?