I'm trying to make a tiny POSIX-compatible sed-like function. However I noticed that the code below is "eating" the backslashes.
input.txt
for mysed ./input.txt "TEST2" "TEST2=\"two\""
call :
TEST1="\\_PR.CP%02d"
TEST2="one"
TEST3="\\_PR.P%03d"
Expected:
TEST1="\\_PR.CP%02d"
TEST2="two"
TEST3="\\_PR.P%03d"
Received:
TEST1="\_PR.CP%02d"
TEST2="two"
TEST3="\_PR.P%03d"
How to modify the code below to preserve all the backslashes? Maybe it's possible to replace a custom printf '%b\n'
format by something better?
#!/bin/sh
# Replaces the lines containing the text '$2' of a file '$1' with a line '$3'.
mysed () {
if [ -f "$1" ] ; then
mysed_tmp="./.mysed"
rm -f $mysed_tmp
while IFS= read -r line
do
case $line in
*"$2"*)
if [ ! -z "$3" ] ; then
printf '%b\n' "$3" >> $mysed_tmp
fi
;;
*)
printf '%b\n' "$line" >> $mysed_tmp
;;
esac
done < "$1"
mv $mysed_tmp $1
return 0
else
return 1
fi
}
echo "TEST1=\"\\\\_PR.CP%02d\"" > input.txt
echo "TEST2=\"one\"" >> input.txt
echo "TEST3=\"\\\\_PR.P%03d\"" >> input.txt
mysed ./input.txt "TEST2" "TEST2=\"two\""
cat ./input.txt
EDIT: replaced '%b\n'
with '%s\n'
, everything is working now as intended.
Look:
$ x="TEST2=\"two\""; printf '%s\n' "$x"
TEST2="two"
$ x='TEST2=\"two\"'; printf '%s\n' "$x"
TEST2=\"two\"
$ TEST1="\\_PR.CP%02d"; printf '%s\n' "$TEST1"
\_PR.CP%02d
$ TEST1='\\_PR.CP%02d'; printf '%s\n' "$TEST1"
\\_PR.CP%02d
Hopefully this will make things clearer:
$ foo() { printf '%%b:<%b>\n%%s:<%s>\n---\n' "$1" "$1"; }
$ foo "TEST2=\\"two\\""
%b:<TEST2= wo\>
%s:<TEST2=\two\>
---
$ foo 'TEST2=\\"two\\"'
%b:<TEST2=\"two\">
%s:<TEST2=\\"two\\">
---
So:
'
not "
.%s
not %b
.