6

I am trying to escape backslash in AWK. This is a sample of what I am trying to do.

Say, I have a variable

$echo $a
hi

The following works

$echo $a | awk '{printf("\\\"%s\"",$1)'}
\"hi"

But, when I am trying to save the output of the same command to a variable using command substitution, I get the following error:

$ q=`echo $a | awk '{printf("\\\"%s\"",$1)'}`
awk: {printf("\\"%s\"",$1)}
awk:               ^ backslash not last character on line

I am unable to understand why command substitution is breaking the AWK. Thanks a lot for your help.

Bill
  • 5,263
  • 6
  • 35
  • 50
  • See [this question](https://stackoverflow.com/questions/57447644/exactly-how-do-backslashes-work-within-backticks) for clear understanding of behaviour of backslashes within backticks – Dhruv Aug 10 '23 at 13:30

3 Answers3

3

Try this:

q=$(echo $a | awk '{printf("\\\"%s\"",$1)}')

Test:

$ a=hi
$ echo $a
hi
$ q=$(echo $a | awk '{printf("\\\"%s\"",$1)}')
$ echo $q
\"hi"

Update:

It will, it just gets a littler messier.

q=`echo $a | awk '{printf("\\\\\"%s\"",$1)}'`

Test:

$ b=hello
$ echo $b
hello
$ t=`echo $b | awk '{printf("\\\\\"%s\"",$1)}'`
$ echo $t
\"hello"

Reference

jaypal singh
  • 74,723
  • 23
  • 102
  • 147
  • 4
    @Lorkenpeist: From the man page of `bash`: **When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, `, or \.**. So, when you found two backslashes their meaning is the usual. Otherwise it will be interpreted literally, so either with 5 or 6 will work. In the former because each two of them, one is output, and the last one has no special meaning. And with the latter because all of them are interpreted and will output three of them, just what you want. – Birei May 28 '13 at 21:50
  • In case someone might be wondering that when the final expression the final expression becomes `q=\"hi"` why are the quotes and backslash not removed here is because this removal is done only on the part that is not output of any type of expansion. Read [quote removal](https://www.gnu.org/software/bash/manual/html_node/Quote-Removal.html). – Dhruv Aug 10 '23 at 20:25
1

Quoting inside backquoted commands is somewhat complicated, mainy because the same token is used to start and to end a backquoted command. As a consequence, to nest backquoted commands, the backquotes of the inner one have to be escaped using backslashes. Furthermore, backslashes can be used to quote other backslashes and dollar signs (the latter are in fact redundant). If the backquoted command is contained within double quotes, a backslash can also be used to quote a double quote. All these backslashes are removed when the shell reads the backquoted command. All other backslashes are left intact.

The new $(...) avoids these troubles.

Uwe
  • 718
  • 4
  • 9
1

Don't get into bad habits with backticks, quoting and parsing shell variables to awk The correct way to do this is:

$ shell_var="hi"

$ awk -v awk_var="$shell_var" -v c='\' 'BEGIN{printf "%s%s\n",c,awk_var}'
\hi

$ res=$(awk -v awk_var="$shell_var" -v c='\' 'BEGIN{printf "%s%s\n",c,awk_var}')

$ echo "$res"
\hi
Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
  • The correct way in this particular case is `q=\\\"$a\"`. There is no need to use command substitution, echo, awk, or a pipeline. – Uwe May 28 '13 at 23:14
  • So the correct way use shell variables and backslashes with awk is not to use awk? I don't think so... Don't take the question literary, it's just an example. – Chris Seymour May 29 '13 at 06:11
  • Sorry, I missed that this was not the OP's real problem but a simplified version. – Uwe May 29 '13 at 09:18