1

I answered this question, but I am stuck on the part where I have to add a single quote also to it.

Like original file is:

$$BATCHCTRL=TEST-012017
$$STATE=CA AZ
$$FROM_DATE=01/10/2017
$$TO_DATE=01/30/2017

New file should be:

$$BATCHCTRL=TEST-012017
$$STATE='CA'
$$FROM_DATE=01/10/2017
$$TO_DATE=01/30/2017

I used

sed -Ei 's/^\$\$STATE=([A-Z]{2}) ([A-Z]{2})/\$\$STATE=\1/g' sed_file

So I got:

$$BATCHCTRL=TEST-012017
$$STATE=CA
$$FROM_DATE=01/10/2017
$$TO_DATE=01/30/2017

but now I am unable to add single quote in it. I tried escaping, used double quotes instead of single quotes, tried without quotes, but none is working.

Prvt_Yadav
  • 5,882

3 Answers3

3

Two options:

Temporarily break out of the single quoted string that is the sed expression, insert "'" (a quoted single quote character) and continue. Repeat for the other quote.

$ sed -E 's/^\$\$STATE=([A-Z]{2}) ([A-Z]{2})/$$STATE='"'"'\1'"'"'/' file
$$BATCHCTRL=TEST-012017
$$STATE='CA'
$$FROM_DATE=01/10/2017
$$TO_DATE=01/30/2017

Note that $ does not have to be escaped in the replacement string.

You could also use \' in place of "'":

$ sed -E 's/^\$\$STATE=([A-Z]{2}) ([A-Z]{2})/$$STATE='\''\1'\''/' file
$$BATCHCTRL=TEST-012017
$$STATE='CA'
$$FROM_DATE=01/10/2017
$$TO_DATE=01/30/2017

or,

Use double quotes around the expression and single quotes as ordinary characters within. This requires that all existing backslashes and $ characters are protected from the shell.

$ sed -E "s/^\\\$\\\$STATE=([A-Z]{2}) ([A-Z]{2})/\$\$STATE='\1'/" file
$$BATCHCTRL=TEST-012017
$$STATE='CA'
$$FROM_DATE=01/10/2017
$$TO_DATE=01/30/2017

The excessive escaping here is needed because you want sed to get the literal string \$ in the regular expression (and just $ in the replacement part). Within double quotes in the shell, \$ is just a literal $. \\$ would be a literal backslash followed by $, and the shell would try to use whatever is after the $ as something to expand ($$ or $STATE for example). Using \\\$, we give a literal backslash followed by a literal $.

I've also removed the g at the end of the sed expression. Since you are anchoring it at the beginning of the line, we don't expect the substitution to be performed more than a single time.

Kusalananda
  • 333,661
1

FWIW, you can use the following to substitute plus slip in single quotes from a bash commandline sed invocation as shown :

 $   sed -e 's/$$STATE=\([A-Z][A-Z]\) [A-Z][A-Z]$/$$STATE='"'\1'/" sed_file

This way you are saved from the "excessive backslashing", known to cause 'backslashitis'.

A few points to ponder:

  1. The $ loses it's metacharacter status when used any place except the last, on the lhs of s/// command. Ofc, you must be in single quotes otw anyway the bash will kick in nd expand vars. Im talking of what sed does.

  2. In the rhs of the s/// command, the $ is not a metacharacter, so no need to escape it.

  3. Sed is to be in -e mode not -re mode.

HTH

1

I Have tried with below method

sed "/^\$\$STATE/s/ .*/'/g" filename| sed "/\$\$STATE/s/=/&'/g"

output

$$BATCHCTRL=TEST-012017
$$STATE='CA'
$$FROM_DATE=01/10/2017
$$TO_DATE=01/30/201