Escaping Quotes in Bash (Embedded Awk)

Escaping quotes in bash (Embedded awk)

The easiest way to deal with this problem is to avoid it. Don't bother trying to escape your script to go on a command line: Pass it on stdin instead.

ssh root@server1 bash -s <<'EOF'
gzip -d /tmp/file.out-20171119.gz
# note that (particularly w/o a cd /tmp) this doesn't do anything at all related to the
# line above; thus, probably buggy as given in the original question.
echo file* | awk -F'[.-]' '{print $1$3".log"}'
EOF

A quoted heredoc -- one with <<'EOF' or <<\EOF instead of <<EOF -- is passed literally, without any shell expansions; thus, $1 or $3 will not be replaced by the calling shell as they would with an unquoted heredoc.


If you don't want to go the avoidance route, you can have the shell do the quoting for you itself. For example:

external_function() {
gzip -d /tmp/file.out-20171119.gz
echo file* | awk -F'[.-]' '{print $1$3".log"}'
}

ssh root@server1 "$(declare -f external_function); external_function"

declare -f prints a definition of a function. Putting that function literally into your SSH command ensures that it's run remotely.

Escaping nested double quotes in awk

The standard advice for Windows to avoid their nightmarish quoting rules is:

a) Don't call the script from Windows. Install cygwin or similar to get a UNIX-like environment and then call the script from that, or...

b) Don't specify the script text on the command line in Windows, save it in a file instead, i.e. put this in a file named foo.awk:

BEGIN { FS="|" }
$4 ~ /JUVENILE/ {sum +=$6}
END {printf "%.3f", sum}

and then execute it as awk -f foo.awk sourcedata.file

How to escape a single quote inside awk

This maybe what you're looking for:

awk 'BEGIN {FS=" ";} {printf "'\''%s'\'' ", $1}'

That is, with '\'' you close the opening ', then print a literal ' by escaping it and finally open the ' again.

Using double quotes in awk

If the awk command is single quoted, the $2 is not interpreted by the shell, but is instead passed as the literal string $2 to awk. awk will then print the second space delimited token in the input string, which in this case is a.

echo "line1 a b c" | awk '{ print $2 }' # prints the second space-delimited token
> a

If the awk command is double quoted, the $2 is interpreted by the shell. Because $2 is empty (in this case), the empty string is substituted. awk sees a command which looks like awk "{ print }", which is an instruction to print everything.

echo "line1 a b c" | awk '{ print }' # prints all input
> line1 a b c

It is also possible to use double qotes, and escape the $, which will cause the $ to not be interpreted by the shell, and instead the $2 string will be passed to awk.

echo "line1 a b c" | awk "{ print \$2 }" # prints the second space-delimited token
> a

How to escape single quotes within single quoted strings

If you really want to use single quotes in the outermost layer, remember that you can glue both kinds of quotation. Example:

 alias rxvt='urxvt -fg '"'"'#111111'"'"' -bg '"'"'#111111'"'"
# ^^^^^ ^^^^^ ^^^^^ ^^^^
# 12345 12345 12345 1234

Explanation of how '"'"' is interpreted as just ':

  1. ' End first quotation which uses single quotes.
  2. " Start second quotation, using double-quotes.
  3. ' Quoted character.
  4. " End second quotation, using double-quotes.
  5. ' Start third quotation, using single quotes.

If you do not place any whitespaces between (1) and (2), or between (4) and (5), the shell will interpret that string as a one long word.

How to make awk ignore the field delimiter inside double quotes?

From the GNU awk manual (http://www.gnu.org/software/gawk/manual/gawk.html#Splitting-By-Content):

$ awk -vFPAT='([^,]*)|("[^"]+")' -vOFS=, '{print $1,$4}' file
"abc@xyz.com,www.example.com",field4
"def@xyz.com",field4

and see What's the most robust way to efficiently parse CSV using awk? for more generally parsing CSVs that include newlines, etc. within fields.

Nested quotes bash

You can still place single quotes as long as the variables are intended to be initially expanded before the whole command string is executed on the shell on the remote server.

sudo ssh server "echo \"$SOMEVAR\"; awk '/pattern/{print \"hello\"}1' file > file.tmp"


Related Topics



Leave a reply



Submit