sed behavior on cygwin inconsistent - windows

i have been facing an issue with a certain sed expression working on one windows system and breaking on other. The shell script is being run on cygwin, where the cygwin and sed versions are identical.
expression:
url=$(echo ${!1} | sed 's/{/\\\{/g'); \
error on the system is :
Error: /usr/bin/sed: -e expression #1, char 2: unterminated `s' command
So when i use it by escaping the braces it works:
url=$(echo ${!1} | sed 's/\{/\\\{/g'); \
But the breaks on the other with error saying:
sed: -e expression #1, char 11: Invalid preceding regular expression
Please help .. stuck with this for some time. Please let me know if you need more details.

for a substitution by \{
echo ${!1} | sed -e 's/{/\\{/g'
or by \\{
echo ${!1} | sed -e 's/{/\\\\{/g')
3 \ and no explicit -e are certainly the problem.
Info: No error with your code on my cygwin (usinf a direct string in place of ${!1}
If you escape the first {, sed is waiting for a number of occurence regex and an closing brace (ex: \{1,\})

Related

sed command containing variable not working

I can't get the syntax for this command right... I need to change a variable in a file where the variable contains a path.
sessionFolderName=/session_`date '+%y%m%d'`_`date '+%H%M'`
sed "s/sessionFolder=.*/sessionFolder=/"$sessionFolder /home/pi/scripts/settings/settings.sh > tmp
mv tmp /home/pi/scripts/settings/settings.sh
However the result is:
sed: -e expression #1, char 35: unknown option to `s'
# You don't need to (and in your case, should not) invoke date command twice.
# Try running following in bash to see the problem.
# $ echo $(date '+%s')_$(sleep 1)_$(date '+%s')
# On a different note, it's better to use $(...) instead of backticks.
sessionFolderName="/session_$(date '+%y%m%d_%H%M')"
# You can use several other separators in sed.
# e.g. :, ;, #, #, _ and even a space
sed "s:sessionFolder=.*:sessionFolder=${sessionFolder}:" /home/pi/scripts/settings/settings.sh > tmp
mv tmp /home/pi/scripts/settings/settings.sh
Refer to this regarding using $() instead of backticks
The problem is with the / char in the start of your variable. This interrupts sed syntax:
[root# ~]# sed "s/sessionFolder=.*/${sessionFolderName}/" text
sed: -e expression #1, char 21: unknown option to `s'
[root# ~]# echo $sessionFolderName
/session_170824_0942
If you escape it using double backslash - \\, it works:
[root# ~]# sed "s/sessionFolder=.*/sessionFolder=\\${sessionFolderName}/" text
sessionFolder=/session_170824_0942
1) You need to escape the / in your input
2) modify the format of the sed command as shown below
sessionFolderName=\\/session_`date '+%y%m%d'`_`date '+%H%M'`
sed "s/sessionFolder=.*/sessionFolder="$sessionFolderName"/" /home/pi/scripts/settings/settings.sh > tmp

Bash script sed

I am trying to use sed in bash script as follows:
#!/bin/bash
for i in `seq 1 10`;
do
j=$(($i-1))
OLD="-option_something something/string1_${j}.txt"
NEW="-option_somehting something/string1_${i}.txt"
sed -e "s/$OLD/$NEW/g" file_to_edit.txt
# sed -e "s/$OLD/$NEW/g" file_to_edit.txt > file_to_edit.txt.tmp && mv file_to_edit.txt.tmp file_to_edit.txt
done
But I keep getting following error:
sed: -e expression #1, char 71: unknown option tos'`
I tried the commented line as well, but it does not work too.
It works fine on command line. I do not know what is the problem in script.
Any suggestions? Thanks.
You have a / in the value of OLD and NEW, which is the same character you're using as the delimiter in your sed expression. So the final expression ends up looking like:
sed -e "s/-option_something something/string1_${j}.txt/-option_somehting something/string1_${i}.txt/g"
Do you see all the / in there? Consider instead:
sed -e "s|$OLD|$NEW|g" file_to_edit.txt
You can use any character as the delimiter for sed's s command.

Sed Regex Error using \1

I keep getting the following error:
sed: -e expression #1, char 29: invalid reference \1 on `s' command's RHS
grep -l 'someFiles' | xargs sed -r 's/<add fileName="\(.+?\)"/\1/g'
I am escaping the () as I have read to do in other files, I have also tried to work through it elsewhere:
https://regex101.com/r/tU9qV4/2
so I know my regex is working, I have also tested my grep, I am actually using a few exclusions and things in the statement, but it's outputting exactly what I need. Why am I still not able to use the \1?

Find and Replace string using sed gives error

I am using shell script. My requirement is to find and replace the string. The string contains "/" char as well. I am getting error sed: -e expression #1, char 18: unterminated `s' command. Can someone tell how should i replace the string which has "/"?
#!/bin/bash
...
search_string="../conf/TestSystem/Inst1.xml"
rep="Inst1/Instrument.xml"
sed -i 's|${line}|${rep}/g' MasterConfiguration.xml
I tried using another sed command but that one also gave error sed: -e expression #1, char 13: unknown option to `s'
sed -e "s/${line}/${rep}/g" MasterConfiguration.xml > tempfile
Whenever you deal with shell-variables you have to get them out of the "sed-string":
For example:
sed -e "s/"${line}"/"${rep}"/g" MasterConfiguration.xml > tempfile
Otherwise sed will treat the chars as-is and search for ${line} literally:
As you see, nothing happens here.
Furthermore, if your variables contain / you need to use another delimiter for sed. I tend to use ~ in such a case, but you're free to use other chars - just be consequent and don't mix them like in your first example-sed-command:
sed 's~'${line}'~'${rep}'/g' //WRONG
sed 's~'${line}'~'${rep}'~g' //RIGHT
Combine both and it will work:
You can try this sed,
sed -i "s#${line}#${rep}#g" MasterConfiguration.xml
Problem:
Instead you have,
sed -i "s|${line}|${rep}/g" MasterConfiguration.xml
It should be,
sed -i "s|${line}|${rep}|g" MasterConfiguration.xml
Syntax:
sed "s|pattern|replacement|g"

SED bad substitution error

Here's my problem, I have written the following line of code to format properly a list of files found recursively in a directory.
find * | sed -e '/\(.*\..*\)/ !d' | sed -e "s/^.*/\${File} \${INST\_FILES} &/" | sed -e "s/\( \)\([a-zA-Z0-9]*\/\)/\/\2/" | sed -e "s/\(\/\)\([a-zA-Z0-9\_\-\(\)\{\}\$]*\.[a-zA-Z0-9]*\)/ \2/"
The second step is to write the output of this command in a script. While the code above has the expected behavior, the problem occurs when I try to store its output to a variable, I get a bad substitution error from the first sed command in the line.
#!/bin/bash
nsisscript=myscript.sh
FILES=*
for f in $(find $FILES); do
v=`echo $f | sed -e '/\(.*\..*\)/ !d' | sed -e "s/^.*/\${File} \${INST\_FILES} &/" | sed -e "s/\( \)\([a-zA-Z0-9]*\/\)/\/\2/" | sed -e "s/\(\/\)\([a-zA-Z0-9\_\-\(\)\{\}\$]*\.[a-zA-Z0-9]*\)/ \2/"`
sed -i.backup -e "s/\;Insert files here/$v\\n&/" $nsisscript
done
Could you please help me understand what the difference is between the two cases and why I get this error ?
Thanks in advance!
Well my guess was that your escaping of underscore in INST_FILES is strange as underscore is not a special character in shell nor in sed. The error disappear when you delete the '\' before '_'
my 2 cents
Parsing inside of backquote-style command substitution is a bit weird -- it requires an extra level of escaping (i.e. backslashes) to control when expansions take place. Ugly solution: add more backslashes. Better solution: use $() instead of backquotes -- it does the same thing, but without the weird parsing and escaping issues.
BTW, your script seems to have some other issues. First, I don't know about the sed on your system, but the versions I'm familiar with don't interpret \n in the substitution as a newline (which I presume you want), but as a literal n character. One solution is to include a literal newline in the substitution (preceded by a backslash).
Also, the loop executes for each found file, but for files that don't have a period in the name, the first sed command removes them, $v is empty, and you add a blank line to myscript.sh. You should either put the filtering sed call in the for statement, or add it as a filter to the find command.
#!/bin/bash
nsisscript=myscript.sh
nl=$'\n'
FILES=*
for f in $(find $FILES -name "*.*"); do
v=$(echo $f | sed -e "s/^.*/\${File} \${INST\_FILES} &/" | sed -e "s/\( \)\([a-zA-Z0-9]*\/\)/\/\2/" | sed -e "s/\(\/\)\([a-zA-Z0-9\_\-\(\)\{\}\$]*\.[a-zA-Z0-9]*\)/ \2/")
sed -i.backup -e "s/\;Insert files here/$v\\$nl&/" $nsisscript
done

Resources