29

Following on from this question about stripping newlines out of text, I want to turn this into a zsh alias as follows:

alias striplines=' awk " /^$/ {print \"\n\"; } /./ {printf( \" %s \",$0);}"'

I've tried escaping the quotes inside the awk script, but I'm getting this error:

awk: (FILENAME=bspsrobustness FNR=1) fatal: division by zero attempted

(The file is called bspsrobustness)

Is there a way to do what I want? I suppose I could turn this into an awk script rather than a zsh alias, is that my best option?

1

3 Answers 3

24

You could use a zsh function instead of an alias. No quoting hoops to jump through.

striplines() {
    awk '... awk body "with quotes" ...' "$@"
}
3
  • And then how would I call it: striplines filename?
    – Seamus
    Commented Feb 24, 2011 at 15:03
  • could you explain what the "$@" is doing?
    – Seamus
    Commented Feb 24, 2011 at 15:10
  • 1
    @Seamus, yes you'd call it exactly like that. The "$@" syntax sends the striplines arguments to awk undisturbed -- necessary if, say, any of your filenames contain spaces: striplines "file 1" "file 2" would sent two filenames to awk. Commented Feb 24, 2011 at 15:35
7

To get an idea of what's going on, run

% alias striplines='print -lr awk " /^$/ {print \"\n\"; } /./ {printf( \" %s \",$0);}"'
% striplines
awk
 /^$/ {print "\n"; } /./ {printf( " %s ",zsh);}

Since the $ characters are in double quotes (when they're expanded after the alias is expanded), they are interpreted by the shell. To get the quoting right, it's easier to put the whole alias definition in single quotes. What's inside the single quotes is what will be expanded when the alias is used. Now that the argument of awk is surrounded in double quotes, it's clear that you need backslashes before \"$.

alias striplines='print -lr awk " /^\$/ {print \"\n\"; } /./ {printf( \" %s \",\$0);}"'

A useful idiom to single-quote a single-quoted string is that '\'' is pretty much a way to put a literal single quote in a single-quoted string. Technically there's a juxtaposition of a single-quoted string, a backslash-quoted ', and another single-quoted string. The juxtaposed empty string '' at the end can be removed.

alias striplines='print -lr awk '\'' /^$/ {print "\n"; } /./ {printf( " %s ",$0);}'\'

After this long explanation, a recommendation: when it's too complicated for an alias, use a function.

6

If you're using zsh, you might also turn on the rcquotes option:

Allow the character sequence '' to signify a single quote within singly quoted strings. Note this does not apply in quoted strings using the format $'...', where a backslashed single quote can be used.

Thus, instead of

alias striplines='print -lr awk '\'' /^$/ {print "\n"; } /./ {printf( " %s ",$0);}'\'

using rcquotes you could write

setopt rcquotes
alias striplines='print -lr awk '' /^$/ {print "\n"; } /./ {printf( " %s ",$0);}'''

or, by using $'...' you could write

alias striplines=$'print -lr awk \' /^$/ {print "\n"; } /./ {printf( " %s ",$0);}\''

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .