2

Say, with zsh one can prefix a command with noglob to "turn off filename generation (globbing)".

I'm looking for a shell where similar approach can be used to disable not only globbing but all kind of expansions. Rationale: Using backslash escaping or quotes for any complex command turns it into a bloody mess which is A) difficult to read and comprehend B) unsuitable for re-use on the other levels of nesting.

3
  • 1
    Maybe show one of those complex command? I've never seen a shell where escaping and quoting becomes problematic in complex commands. What usually is happening if you mess things up is that you're trying to inject shell variables as code into strings that you evaluate, rather than passing data around as arguments as ordinary.
    – Kusalananda
    Commented Aug 21, 2022 at 9:19
  • 1
    If you're regularly doing things where quoting and escaping is a serious problem, then you need to learn a better scripting language, one where such things are not a problem. shell is a shit language for anything but getting other programs to do any work, and fancier versions of shell like zsh don't actually solve the problem, they only obscure it a little. Try perl or python. If you're used to writing stuff in sh + sed + awk + tr + all the usual unix tools then perl would probably be best.
    – cas
    Commented Aug 21, 2022 at 9:54
  • 1
    For some problems, writing a program in C is a better solution. Shell is powerful, but it is not a general-purpose language. Commented Aug 21, 2022 at 12:54

1 Answer 1

3

In zsh, you can do:

set -o interactive_comments -o extendedglob
alias '@=:;# '
handle_@() {
  local match
  if [[ $1 = (#b)@\##[[:space:]]##([^[:space:]]##)[[:space:]]#(*) ]] $match
}
preexec_functions+=(handle_@)

And then prefix your commands with @ (has to make up the whole editing buffer, no foo; @ cmd nor foo | @ cmd, etc) for the first word after that to be taken as the command name, and the rest of the line to be passed as one single argument to that command:

$ @ echo asd'@123 # # qwe $x ``
asd'@123 # # qwe $x ``

That means that one argument can't start with whitespace nor contain newline characters though.

That works by aliasing @ with :;#, the : noop command (so preexec hooks be run) followed by the comment leader, so the rest of the line is parsed as a comment and discarded.

In the preexec hook, we split that unprocessed line (in $1) into the command and arg. Note the \## to allow # after @ in there to work around in bug in older versions of zsh (5.3 or older). Note that it won't work in 4.3.12 (from 2011) or older where the comment is not included in prexec()'s $1.

Of interest, zsh also has the quote-region and quote-line widgets (bound to Alt+" and Alt+' respectively by default in emacs mode) which can save the hassle of do proper quoting by yourself.

For, instance, you could do:

$ perl -e Ctrl+Space$x = 'whatever';...Alt+"

Where Ctrl+Space or Ctrl+@ (upon which terminals usually send a NUL character), sets the start of the region.

Upon Alt+", that would be transformed to:

perl -e '$x = '\''whatever'\'';...'

with the region now quoted. See also https://stackoverflow.com/q/5407916 for how to set the region (selection) with Shift + arrow/motion keys.

9
  • 1
    Thank you Stéphane, but that doesn't seem to work on macOS' zsh at least.
    – poige
    Commented Aug 21, 2022 at 9:08
  • @poige, maybe you have an older version of zsh (see edit)? Does it also not work with zsh -f? Commented Aug 21, 2022 at 10:16
  • As to quot-region/line — yeah, I'm aware of it, but there's no such a thing as "unquote" so it's one way ticket and finally you end up with the same quoted/escaped mess which I described as not wanted in the original posting.
    – poige
    Commented Aug 21, 2022 at 15:32
  • @poige, there's undo though, and writing an unquote widget wouldn't be so hard using the Q parameter expansion flag. You've also yet to show an example of the kind of mess you want to avoid. I've never felt this kind of need in the 25+ years I've been using shells on a daily basis. Commented Aug 21, 2022 at 17:08
  • @poige, if that handle_@ still doesn't work for you (or whoever upvoted your comment above) in zsh -f, can you please indicate what you see after entering functions -t handle_@ and then @ echo ;#$', and which version of zsh you're using? Commented Aug 21, 2022 at 17:11

You must log in to answer this question.

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