1

I'm going crazy on a simple thing. I have written the following line that is amazingly working:

name=$(echo $name | sed 's/"//g' | sed 's/^ //' | sed 's/ $//' | sed "s/'/\\\'/")

I'm trying to reduce sed to only one command instead of four, and I wrote the following line that doesn't work, and I cannot manage to make it work:

name=$(echo $name | sed 's/"//g; s/^ //; s/ $//; s/\'/\\\'/g')

I get:

sed: 1: "s/"//g; s/^ //; s/ $//; ...": unterminated substitute in regular expression

What am I doing wrong? I can't see the syntax error, I've tried to rewrite it many times, the line with 4 sed works, but this where I try to put all in one sed it doesn't.

Thank you very much for your help!

oguz ismail
  • 1
  • 16
  • 47
  • 69
Red
  • 63
  • 6
  • Use a good editor. Even coloring on stackoverflow here is hinting you. – KamilCuk Aug 09 '21 at 21:42
  • You should double-quote variable references (e.g. `echo "$name"` instead of just `echo $name`) to prevent weird parsing before the value even gets to `sed`. See ["I just assigned a variable, but `echo $variable` shows something else"](https://stackoverflow.com/questions/29378566/i-just-assigned-a-variable-but-echo-variable-shows-something-else) (but note that this doesn't apply *just* to `echo`; it applies almost everywhere). [shellcheck.net](https://www.shellcheck.net) is good at spotting common mistakes like this. – Gordon Davisson Aug 10 '21 at 00:20
  • Good suggestion Gordon, thank you! – Red Aug 10 '21 at 12:48

4 Answers4

2

You cannot embed a single quote in a single-quoted string, no matter now many escapes you use: 3.1.2.2 Single Quotes

You can use sed's -e option to chain the commands and give you the most quoting flexibility:

sed -e 's/"//g' -e 's/^ //' -e 's/ $//' -e "s/'/\\\'/"
# or
sed -e 's/"//g; s/^ //; s/ $//' -e "s/'/\\\'/"
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • Thank you Glenn, I firstly missed the option -e, then I had no idea I could not use single quotation mark inside a SQM, then the escapes were completely useless, now it's all clear, thank you very much for your help! – Red Aug 09 '21 at 21:53
2

This might work for you (GNU sed):

sed -E 's/^ |"| $//g;s/'\''/\\&/g' file

Use alternation to remove a space at the start/end of a line or double quote.

Replace a single quote by an escaped single quote.

It is not possible to have solution with a single substitution as the RHS of the substitution is different in one of the four cases i.e. first 3 cases remove strings whereas the fourth case adds one.

If, however you intend to remove the single quote, use:

sed -E 's/^ |["'\'']| $//g' file
potong
  • 55,640
  • 6
  • 51
  • 83
1

You can also abut quotes anywhere to need to switch them. Just be careful of interpolation, per usual with double-quotes:

Instead of

name=$(echo $name | sed 's/"//g; s/^ //; s/ $//; s/\'/\\\'/g')

do

$ name=$(echo $name | sed 's/"//g; s/^ //; s/ $//;'" s/\'/\\\'/g")

although I think what you want may actually be

$ name=$(echo $name | sed 's/"//g; s/^ //; s/ $//;'" s/'//g")

Adjacent quotes are just like any other adjacent characters. With no intervening whitespace, they constitute a continuing string.

James K. Lowden
  • 7,574
  • 1
  • 16
  • 31
  • I've never seen the $ with a space before a variable, I will need to read about it. Thank you very much James I appreciated your help. – Red Aug 09 '21 at 22:14
  • @Renato the `$` at the start of the line is just a very common prompt as set in `PS1`, it has nothing to do with the variable or any part of the command. – Ed Morton Aug 10 '21 at 04:15
  • Sorry James, I thought was part of a script, it's obviously the bash user symbol, sorry again. – Red Aug 10 '21 at 12:46
  • `echo $name` is really bad. Try `a=' -n a b c '; echo $a` (with multi spaces) and you get `a b c` (with single spaces). Better is `echo "$name"`. Even better is `sed ... <<< "$name"` without echo. – Wiimm Nov 24 '21 at 07:49
  • @Wiimm, I seen no reason in SO answers to supply fully generalized code unless the question regards generalization or portability. Perfect accuracy comes at the cost of clarity; a simple answer that gets to the point is better than a fully general one that obscures it. (I wouldn't recommend `<<<`, though, because it's specific to bash.) – James K. Lowden Nov 29 '21 at 16:30
1

You can use the third method of bash quoting: $'...'. Here C like escapes are possible. So your sed command can be:

sed $'s/"//g; s/^ //; s/ $//; s/\'/\\\'/g'

But if you want, that the input a'b becomes a\'b, then use

sed $'s/"//g; s/^ //; s/ $//; s/\'/\\\\\'/g'

Analyzing \\\\\': bash reads it as \\'. And sed reads it as \'.

Wiimm
  • 2,971
  • 1
  • 15
  • 25
  • I will need to read about ```$'...'```, since I've never seen it before. Thank you Wiimm I appreciated the suggestion! – Red Aug 09 '21 at 22:13