145

I want do the following

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

But escaping single quote this way does not work

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

How to do this? Thanks for help.

codeforester
  • 39,467
  • 16
  • 112
  • 140
  • A number of languages escape quotes by putting two of them in a row, maybe try that. – joshuahealy Mar 27 '12 at 23:08
  • I tried awk 'BEGIN {FS=" ";} {printf "''%s'' ", $1}', but no single quote was printed. –  Mar 27 '12 at 23:19
  • [This Page](http://www.gnu.org/software/gawk/manual/html_node/Quoting.html) says that including a single quote in a single-quoted string is impossible. Maybe you'll have to convert to double quotes. – joshuahealy Mar 27 '12 at 23:24
  • 4
    It is impossible, but *two* adjacent single-quoted shell strings glue together into one parameter. And two single-quoted shell strings glued by non-whitespace characters also glue into one big glob: `'abc'd'ef'` is `abcdef`: literal plus `d` plus literal. The `d` is outside of the quotes, and you can replace that `d` it with `\'` to make `'abc'\''ef'` which evaluates to `abc'ef`. – Kaz Mar 28 '12 at 01:16

9 Answers9

214

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.

fedorqui
  • 275,237
  • 103
  • 548
  • 598
Steve
  • 51,466
  • 13
  • 89
  • 103
  • 61
    It has nothing to do with awk. The `'` character closes the opening `'` shell string literal. The shell literal does not support a backslash escape for this. The sequence `'\''` does the trick: it closes the single-quote literal, specifies the quote character (using an escape that *is* supported outside of single-quote literals) and then re-opens a new single-quote literal. You can think of it as a four-character escape sequence to get a single quote. :) – Kaz Mar 28 '12 at 01:14
  • 2
    @Steve: Thanks a lot for your very useful answer. You saved me a lot of headaches! – John Slegers Jun 11 '14 at 08:12
  • @Kaz In some way it *IS* an issue evoked by `awk`, albeit indirectly. Because if `awk` allowed us to use double quotes (e. g. `"{printf $2}"` instead of the required `'{printf $2}'`), things would be way easier in handling single quotes inside `awk` expressions, let alone `/string/` matches. `sed` allows its expressions to be enclosed in double quotes; same with `grep`; so why not `awk`?? – syntaxerror Jun 09 '15 at 17:06
  • 5
    @syntaxerror What quotes you use for preparing arguments for invoking `awk` are purely a matter of the command interpreter you are using to compose command lines. The `'{printf $2}'` gets turned into some argument for an `execve` system call or similar, where it just looks like a null terminated C string without any single quotes. Awk never sees the quotes, and neither does sed. You can in fact use double-quotes, but double quotes do not prevent the shell's expansion of `$2`, so you have to escape the dollar sign with a backslash to make it literal: `"{printf \$2}"`. – Kaz Jun 09 '15 at 17:44
  • 5
    @syntaxerror By custom, an in-line awk script is usually escaped with single quotes, because awk syntax often contains lexical elements which are special to the shell, such as double quoted string literals, and numbered fields denoted by dollar signs. If a sed regular expression (or whatever) contains shell syntax, you also have to be careful. `sed -e "s/$FOO/$BAR/"` will not work if the intent is to replace the literal text `$FOO` with `$BAR`. The easiest way would be `sed -e 's/$FOO/$BAR/`. – Kaz Jun 09 '15 at 17:49
  • @Kaz You're a marvel. So all I forgot to do when testing awk deliberately with double quotes (not single ones as usual) was to escape the dollar sign for the `$2`? Well, I'll be damned, it works that way - even though before I would have made a bet that enclosing awk expressions in double quotes is a thing to be avoided in the first place. Anyways: though no beginner any more, I still won't stop learning new things every day, even if only by putting up such (meta-)questions. :) Thank you very much. By this technique one might even do without a temp variable for a single quote. – syntaxerror Jun 09 '15 at 18:12
  • 1
    @syntaxerror If you enclose awk programs in double quotes, you will run into a lot of of escaping, like `awk "{ print \"abc\", \$1 }"`. Any time a double quote appears in the awk program, it has to be escaped so that it doesn't close the shell quote. And compare this: `awk '{print "\\"}'` (print a backslash) versus what it takes with double quotes: `awk "BEGIN {print \"\\\\\" }"`, Phew! Both quotes have to be escaped, and both backslashes. The shell converts `\\ ` to `\ ` so we need `\\\\ ` to encode `\\ `. – Kaz Jun 09 '15 at 18:19
  • @Kaz Again: I concede that this technique is really only suitable for special cases, like an _extraordinarily high amount of single quotes to be handled_ in one and the same `awk` expression. But I can't but agree that using this technique in too general cases is rather a thing to be discouraged. Anyways, it's good to know about it "just in case". :) – syntaxerror Jun 09 '15 at 21:52
  • Unfortunately, though accepted this is the wrong answer. The right answer is http://stackoverflow.com/a/20664521/1745001 since it works clearly and simply in all cases, even on non-UNIX OSes and even if your script gets larger and you need to move it into a file and execute it as `awk -f script`. – Ed Morton Aug 03 '16 at 05:01
98

A single quote is represented using \x27

Like in

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

Source

mklement0
  • 382,024
  • 64
  • 607
  • 775
tiagojco
  • 1,123
  • 8
  • 6
45

Another option is to pass the single quote as an awk variable:

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

Simple example with string concatenation:

# Prints 'test me', *including* the single quotes.
awk -v q=\' '{ print q $0 q }' <<<'test me'
mklement0
  • 382,024
  • 64
  • 607
  • 775
20
awk 'BEGIN {FS=" "} {printf "\047%s\047 ", $1}'
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
Sergio K
  • 201
  • 2
  • 2
  • 1
    As long as I remember that `\047` is the octal escape sequence for the single-quote character, I find this alternative to be the most readable. – Anthony Geoghegan Jan 11 '19 at 17:54
7

For small scripts, an optional way to make it readable is to use a variable like this:

awk -v fmt="'%s'\n" '{printf fmt, $1}'

I found it convenient in a case where I had to produce many times the single-quote character in the output and the \047 were making it totally unreadable.

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
user1708042
  • 1,740
  • 17
  • 20
1

When you are using awk in the command line, you don't have to use the BEGIN block to define the field separator (FS) you can only use -F" " like:

awk -F" " {printf "\047%s\047 ", $1}'

saves you some typing. :)

0

this is how to print a single quote in awk: "\047"

example:

for i in aA bB cC ; do echo $i | awk '{print "\047"$1"\047"}' ; done

'aA'
'bB'
'cC'
-1

UPDATE 1 : more hands free approach to the $1 single quoting problem :

 1  echo " 123  xyz 456 abc " 

    '123'

        
{m,g}awk 'BEGIN { __=_
                  OFS =  sprintf("%c",
                    ++_  +_++*_+_++^++_+_*++_)
            _+=_^= FS  = "^|[[:space:]]+"
      } NF +=_ ==( NF = _)'

===========================

mawk has, by far, the most concise syntax to wrap lines in single quotes without a printf statement :

gawk 'NF+=   substr(!_, $2 =$_ ($_=_))' FS='^$' OFS='\47'
nawk '$2 =$-_ substr(_, $-_=_, NF = 3)' FS='^$' OFS='\47'

mawk '$++NF=$_ ($_=_)' FS=^$ OFS=\\47

INPUT

<( [[[a]]]bc:
              뀿 123=)>

OUTPUT

' [[[a]]]bc:
             뀿 123='

I intentionally wrapped it in <(…)> to point out there's leading edge space. The gap in between the two lines is a \f : form feed \014.

That said, this only wraps lines without escaping single quotes within the line itself.

To use sub() instead, it'll look like :

{m,n,g}awk -F'^$' 'sub(".*","\47&\47")'
RARE Kpop Manifesto
  • 2,453
  • 3
  • 11
-1

Another way: awk 'BEGIN {FS=" ";} {printf "%c%s%c ", 39, $1, 39}'

Use %c and give the ASCII code number for single quotes, which is 39. By the way, if you need to print double quotes, the ASCII code is 34!

MyICQ
  • 987
  • 1
  • 9
  • 25
Frauke
  • 1
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 27 '22 at 17:21