Saturday, October 8, 2022

[SOLVED] sed: -e expression #1, char 4: unknown command: `\'

Issue

I have written a script that takes a txt file from a folder and I want to insert a blank line at the end of the file, and then write to it. But I have a problem, because the console returns: sed: -e expression #1, char 4: unknown command: `'.

This is code:

adb shell "sudo cp /boot/uEnv.txt /home/rock/"
adb shell "sudo sed -i '$s/$/\n/' /home/rock/uEnv.txt"
adb shell "sudo sed -i '$i extraargs=rtl8723ds.rtw_initmac=\"MACAUXTXT\"' /home/rock/uEnv.txt"
adb shell "sudo sed -i "s/MACAUXTXT/$(cat /sys/class/net/wlan0/address | sed 's/.\{9\}//' | sed 's/^/00:e0:4c:/' )/" /home/rock/uEnv.txt"
adb shell "sudo cp /home/rock/uEnv.txt /boot/"
adb shell "sudo cp /home/rock/Service/20-rock.conf /usr/lib/NetworkManager/conf.d/"
adb shell "sudo rm /home/rock/Service/rockpi-backup.sh"
adb shell "sudo rm /home/rock/Service/20-rock.conf"
adb shell "sudo rm /home/rock/uEnv.txt"

This is problem: enter image description here


Solution

The issue is with nested quoting:

adb shell "sudo sed -i '$s/$/\n/' /home/rock/uEnv.txt"

The shell that runs the adb command processes all of its arguments, including the sudo ... part in double quotes. Since double quotes allow variable expansion by the shell, $s is expanded before sed or even sudo is executed. Depending on what you have stored in the variable named s, it is substituted and finally processed by sed. If you don't have an s variable, an empty string is substituted and $s disappears.

You can see for yourself if you substitute echo for adb:

echo shell "sudo sed -i '$s/$/\n/' /home/rock/uEnv.txt"

shell sudo sed -i '/$/\n/' /home/rock/uEnv.txt

Now sed's middle argument is /$/\n/ instead of $s/$/\n/. /$/ is interpreted as a regular expression filter to decide which lines to operate on, and \n/ as the command and its arguments. Since \ is not a valid command, you get the error described.

There are several ways to go about this.

I can't name a good solution off the top of my head, but one solution is to escape the dollar sign in the top-most shell so it is passed untouched to the subshell:

adb shell "sudo sed -i '\$s/\$/\n/' /home/rock/uEnv.txt"

I escaped the second dollar symbol for good measure as well, although in your case, it has no effect. It is not substituted, because / is not a legal variable name. However, if you later decided to e.g. change the sed command's separator to # to, for instance, deal with file names in the pattern or substitution string, the second dollar symbol would already become a problem, because # is the name of the argument-count shell variable.



Answered By - Larry
Answer Checked By - Pedro (WPSolving Volunteer)