28

Can't figure out how to escape everything while using awk.

I need to enclose each input string with with single quotes, e.g.

input
string1
string2
string3

output 'string1' 'string2' 'string3'

Been fighting with escaping ' " $0 and everything else and I just cannot make it work. Either $0 is passed to bash directly, or something else happens.

8 Answers8

55

Here are a couple of ways:

  1. use octal escape sequences. On ASCII-based systems where ' is encoded as byte 39 (octal 047), that would be:

    awk '{print "\047" $0 "\047"}' input
    'string1'
    'string2'
    'string3'
    
  2. pass the quote as a variable

     $ awk -v q="'" '{print q $0 q}' input
     'string1'
     'string2'
     'string3'
    
steeldriver
  • 81,074
  • 2
    "\047" has never crossed my mind. Wow. Thank you. – Artem S. Tashkinov Jun 16 '20 at 12:38
  • 4
    Or save your awk script in a file script.awk to execute as awk -f script.awk input and then you can just do { print "'" $0 "'" } or { printf "'%s'\n", $0 }. The inability to use 's in a '-delimited script is a shell issue, not an awk issue. – Ed Morton Jun 16 '20 at 22:26
  • Any escaped octal from man ascii is good in awk. Even \000 for NUL (in GNU/awk but not mawk) and \042 for ". – Paul_Pedant Jun 17 '20 at 08:51
  • 1
    I recommend adding #3: escape the quote at the shell level: awk '{ print "'\''" $0 "'\''" }' input and #4 use double quotes at the shell level: awk "{print \"'\" \$0 \"'\" }" input. Since this is the accepted answer and is already listing multiple methods, it might as well also include those alternatives. – mtraceur Jun 17 '20 at 22:06
18

In awk code, just put the apostrophe inside double quotes. You can concatenate strings by putting them next to each other (juxtaposition), no matter how these strings are constructed (literal, variable, field reference, parenthesized expression, …).

{ print "'" $0 "'" }

If this awk code is included in a shell script and the awk code is in a single-quoted literal, you have to arrange to pass the single quote character to awk. Use single-quote-backslash-single-quote-single-quote '\'' to include a single quote character in a single-quoted shell literal.

awk '{ print "'\''" $0 "'\''" }'

Alternatively, express the awk code without using a single quote character. You can use a backslash followed by three octal digits to represent any character in a string literal in awk. For a single quote on ASCII based systems, that's \047.

awk '{ print "\047" $0 "\047" }'
  • 2
    awk '{ print "'\''" $0 "'\''" }' this is just crazy. – Artem S. Tashkinov Jun 16 '20 at 12:47
  • 1
    @ArtemS.Tashkinov It's also by far the superior solution when it comes to portability, and I would argue is more understandable to someone who knows shell as well as they ought to if they're using shell than octal escapes. '\'' is something anyone who does shell scripting should internalize as the way to escape single quotes in a single quoted shell string, especially because single quoted strings are the robust/portable/safest way to escape arbitrary strings in all Bourne-like shells. But alternatively you could put the awk code in a double quoted string: awk "{print \"'\" \$0 \"'\" }" – mtraceur Jun 17 '20 at 22:02
8

Note that you don't need awk for that.

You can use the paste basic utility instead:

 < input paste -d "'" /dev/null - /dev/null

It would be more efficient and have fewer limitations than awk-based or sed-based solutions.

6

The awk code just needs to be

{ print "'" $0 "'" }

You could put that in a file, so you don't need to quote anything:

$ printf 'a\nb\n' | awk -f quote.awk 
'a'
'b'

Or use a double-quoted string, and escape the quotes and the dollar sign:

$ printf 'a\nb\n' | awk "{ print \"'\" \$0 \"'\" }"

Or in Bash/ksh/zsh, use the $'...' form of quotes, which allow you to escape the single quote inside:

$ printf 'a\nb\n' | awk $'{ print "\'" $0 "\'" }'
ilkkachu
  • 138,973
3

Without using backslashes or other tricks:

$ printf "hello\nworld\n" | awk '{print "'"'"'" $1 "'"'"'"}'
'hello'
'world'
V P
  • 131
2

you can use the sed command too.

<infile sed -E "s/^|$/'/g"

or

<infile sed -E "s/.*/'&'/" 
αғsнιη
  • 41,407
1

One way to enrobe the string in single quotes is via the printf command gnu xargs :

< file xargs -d'\n' printf "'%s'\n"

Perl

perl -sple '$_="$q$_$q"' -- -q=\'  file

Using GNU sed :

sed -e "G;H;z;x;y/\n/'/" file 
-1
sed -e "s/^/'/g" -e "s/$/'/g" file

output

'string1'
'string2'
'string3'