zsh-users
 help / color / mirror / code / Atom feed
* protect spaces and/or globs
@ 2021-02-09 20:42 Ray Andrews
  2021-02-09 21:05 ` Lawrence Velázquez
  2021-02-09 21:08 ` Peter Stephenson
  0 siblings, 2 replies; 23+ messages in thread
From: Ray Andrews @ 2021-02-09 20:42 UTC (permalink / raw)
  To: Zsh Users

grep allow multiple filespecs of course, and if there are spaces they 
have to be quoted naturally:

$ grep 'some string' filename 'filename with spaces' more_files*

My wrapper around grep has a problem with that tho because when I'm 
grabbing the filespecs if I do something like this:

while [[ -n "$1" ]]; do
         ffilespec+=" $1"
         shift
done

Obviously the final list of files is chaos once the original enclosing 
single quotes are stripped off as they are.  Trying:

while [[ -n "'$1'" ]]; do

... as a brute force addition of single quotes works fine with filenames 
with spaces but it also kills any glob expansions. Can I have it both 
ways? I think I need to preserve any single quotes I add on CL verbatim 
rather than trying to add them myself in the code.  The various (q) 
family flags don't seem to work.  The closest I can get is to both 
single quote and backslash the spaces as the input to my wrapper:

g 'some string' filename 'filename\ with\ spaces' more_files*

... and that's not so bad, but I'm betting there's an elegant way. Hafta 
somehow not break the middle filespec on those spaces even without the 
backslashes.  And preserve the single quotes. Basically the arguments 
should pass thru the function absolutely unmolested and grep should get 
them exactly as I type them.





^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-09 20:42 protect spaces and/or globs Ray Andrews
@ 2021-02-09 21:05 ` Lawrence Velázquez
  2021-02-09 21:08 ` Peter Stephenson
  1 sibling, 0 replies; 23+ messages in thread
From: Lawrence Velázquez @ 2021-02-09 21:05 UTC (permalink / raw)
  To: Ray Andrews; +Cc: zsh-users

> On Feb 9, 2021, at 3:42 PM, Ray Andrews <rayandrews@eastlink.ca> wrote:
> 
> grep allow multiple filespecs of course, and if there are spaces they have to be quoted naturally:
> 
> $ grep 'some string' filename 'filename with spaces' more_files*
> 
> My wrapper around grep has a problem with that tho because when I'm grabbing the filespecs if I do something like this:
> 
> while [[ -n "$1" ]]; do
>         ffilespec+=" $1"
>         shift
> done

What does your wrapper do that requires accreting a scalar like
this? Simply running

	grep $@

would work without issue.

> Obviously the final list of files is chaos once the original enclosing single quotes are stripped off as they are.  Trying:
> 
> while [[ -n "'$1'" ]]; do
> 
> ... as a brute force addition of single quotes works fine with filenames with spaces but it also kills any glob expansions.

This conditional will always return 0. I assume your loop runs
'break' at some point.

vq

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-09 20:42 protect spaces and/or globs Ray Andrews
  2021-02-09 21:05 ` Lawrence Velázquez
@ 2021-02-09 21:08 ` Peter Stephenson
  2021-02-09 23:45   ` Ray Andrews
  1 sibling, 1 reply; 23+ messages in thread
From: Peter Stephenson @ 2021-02-09 21:08 UTC (permalink / raw)
  To: zsh-users

On Tue, 2021-02-09 at 12:42 -0800, Ray Andrews wrote:
> grep allow multiple filespecs of course, and if there are spaces they 
> have to be quoted naturally:
> 
> $ grep 'some string' filename 'filename with spaces' more_files*
> 
> My wrapper around grep has a problem with that tho because when I'm 
> grabbing the filespecs if I do something like this:
> 
> while [[ -n "$1" ]]; do
>          ffilespec+=" $1"
>          shift
> done

This is what arrays are for.

unsetopt shwordsplit # leave poor unsuspecting spaces alone
filespec=()

while [[ -n $1 ]]; do
  filespec+=($1)
  shift
done

In this case, actually, all you're doing is the equivalent of
a single array assignment.

filespec=("$@")

pws



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-09 21:08 ` Peter Stephenson
@ 2021-02-09 23:45   ` Ray Andrews
  2021-02-10  0:22     ` Lawrence Velázquez
  0 siblings, 1 reply; 23+ messages in thread
From: Ray Andrews @ 2021-02-09 23:45 UTC (permalink / raw)
  To: zsh-users

On 2021-02-09 1:08 p.m., Peter Stephenson wrote:
>
>> In this case, actually, all you're doing is the equivalent of
>> a single array assignment.
>>
>> filespec=("$@")
>>
>> pws
It doesn't seem to solve the problem.  Here's a real example:

$ g ,H 'execute' 'g,46,w4 now default' f
... The search string is 'execute' and the two target files follow. But 
after zsh is finished stripping of the quotes the final grep command 
looks like this:

GREP_COLOR='01;33' grep --color=always -iFIHn -d skip -- 'execute' 
g,46,w4 now default  f

... and of course it won't work due to the spaces.  Input via an array 
seems to make no difference.  (Unless I'm doing it wrong.)  If I do this:

$ g ,H 'execute' 'g,46,w4\ now\ default' f
... I get:

GREP_COLOR='01;33' grep --color=always -iFIHn -d skip -- 'execute' 
g,46,w4\ now\ default  f
... which works fine.  Finally,:

$ g ,H 'execute' g,46,w4\ now\ default f
... gives:

GREP_COLOR='01;33' grep --color=always -iFIHn -d skip -- 'execute' 
g,46,w4 now default  f
... and again the unquoted spaces screw it up.  Is there any way to 
force the single quotes to pass through as literals?

Lawrence:

It's all rather complicated, my wrappers do all sorts of mischief before 
calling grep.

BTW Peter I'm sure enjoying your User's Guide.  It should fortify me 
enough to finally read the manual.






^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-09 23:45   ` Ray Andrews
@ 2021-02-10  0:22     ` Lawrence Velázquez
  2021-02-10  0:51       ` Ray Andrews
  0 siblings, 1 reply; 23+ messages in thread
From: Lawrence Velázquez @ 2021-02-10  0:22 UTC (permalink / raw)
  To: Ray Andrews; +Cc: zsh-users

> On Feb 9, 2021, at 6:45 PM, Ray Andrews <rayandrews@eastlink.ca> wrote:
> 
> On 2021-02-09 1:08 p.m., Peter Stephenson wrote:
>> 
>>> In this case, actually, all you're doing is the equivalent of
>>> a single array assignment.
>>> 
>>> filespec=("$@")
>>> 
>>> pws
> It doesn't seem to solve the problem.  Here's a real example:
> 
> $ g ,H 'execute' 'g,46,w4 now default' f
> ... The search string is 'execute' and the two target files follow. But after zsh is finished stripping of the quotes the final grep command looks like this:
> 
> GREP_COLOR='01;33' grep --color=always -iFIHn -d skip -- 'execute' g,46,w4 now default  f
> 
> ... and of course it won't work due to the spaces.  Input via an array seems to make no difference.  (Unless I'm doing it wrong.)  If I do this:
> 
> $ g ,H 'execute' 'g,46,w4\ now\ default' f
> ... I get:
> 
> GREP_COLOR='01;33' grep --color=always -iFIHn -d skip -- 'execute' g,46,w4\ now\ default  f
> ... which works fine.  Finally,:
> 
> $ g ,H 'execute' g,46,w4\ now\ default f
> ... gives:
> 
> GREP_COLOR='01;33' grep --color=always -iFIHn -d skip -- 'execute' g,46,w4 now default  f
> ... and again the unquoted spaces screw it up.  Is there any way to force the single quotes to pass through as literals?

How are you assembling the grep command? How are you executing it?

> Lawrence:
> 
> It's all rather complicated, my wrappers do all sorts of mischief before calling grep.

For the less clairvoyant of us, your refusal to reveal anything but
the smallest slice of your actual code makes it rather difficult
to help.

vq

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-10  0:22     ` Lawrence Velázquez
@ 2021-02-10  0:51       ` Ray Andrews
  2021-02-10  1:46         ` Lawrence Velázquez
  2021-02-10  1:52         ` Greg Klanderman
  0 siblings, 2 replies; 23+ messages in thread
From: Ray Andrews @ 2021-02-10  0:51 UTC (permalink / raw)
  To: zsh-users

On 2021-02-09 4:22 p.m., Lawrence Velázquez wrote:
> For the less clairvoyant of us, your refusal to reveal anything but
> the smallest slice of your actual code makes it rather difficult
> to help.
>
I'm trying to keep is as simple as possible because the totality of the 
thing doesn't
matter, just the specific problem.  When a function argument will end up 
making
an argument to grep, and the argument to grep must have single quotes, 
but the single
quotes typed in the function argument are stripped off. What's the 
solution? grep must
have " $ grep 'file name'  " with intact quotes but zsh always strips 
them off.   There
must be a solution.  Or perhaps I'm stuck with " $ grep 'file\ name' -- 
seems the single
quotes preserve the backlash which in turn forces 'file name' to be a 
single word as
wanted.  It's ok, but I wonder if there's a better way.  I thought the 
(q) flag might
do it.  Memory tickles that I learned how to do this once.

Hey, just fiddling around with it right now and:

$ g ,H 'execute' "'g,46,w4 now default'" f
... double quote the single quotes and the single quotes remain. Logical 
too, outer
quotes will be stripped, so just throw in another set.  Final grep is:

GREP_COLOR='01;33' grep --color=always -iFIHn -d skip -- 'execute' 
'g,46,w4 now default' f
... all good.





^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-10  0:51       ` Ray Andrews
@ 2021-02-10  1:46         ` Lawrence Velázquez
  2021-02-10  2:25           ` Ray Andrews
  2021-02-10  1:52         ` Greg Klanderman
  1 sibling, 1 reply; 23+ messages in thread
From: Lawrence Velázquez @ 2021-02-10  1:46 UTC (permalink / raw)
  To: Ray Andrews; +Cc: zsh-users

> On Feb 9, 2021, at 7:51 PM, Ray Andrews <rayandrews@eastlink.ca> wrote:
> 
> On 2021-02-09 4:22 p.m., Lawrence Velázquez wrote:
>> For the less clairvoyant of us, your refusal to reveal anything but
>> the smallest slice of your actual code makes it rather difficult
>> to help.
>> 
> I'm trying to keep is as simple as possible because the totality of the thing doesn't
> matter, just the specific problem.

Imagine developing stomach pain, self-diagnosing an ulcer, and
refusing to answer doctors' questions about medication, diet,
existing conditions, or anything not ulcer-related because you're
"trying to keep it as simple as possible because the totality of
the thing doesn't matter, just the specific problem", which you
have already decided is an ulcer and cannot possibly be anything
other than an ulcer.

> When a function argument will end up making
> an argument to grep, and the argument to grep must have single quotes, but the single
> quotes typed in the function argument are stripped off. What's the solution? grep must
> have " $ grep 'file name'  " with intact quotes but zsh always strips them off.

grep does not need those arguments to have single quotes. It needs
them to remain a single word, which is related but not identical.

> There
> must be a solution.  Or perhaps I'm stuck with " $ grep 'file\ name' -- seems the single
> quotes preserve the backlash which in turn forces 'file name' to be a single word as
> wanted.  It's ok, but I wonder if there's a better way.  I thought the (q) flag might
> do it.  Memory tickles that I learned how to do this once.
> 
> Hey, just fiddling around with it right now and:
> 
> $ g ,H 'execute' "'g,46,w4 now default'" f
> ... double quote the single quotes and the single quotes remain. Logical too, outer
> quotes will be stripped, so just throw in another set.  Final grep is:
> 
> GREP_COLOR='01;33' grep --color=always -iFIHn -d skip -- 'execute' 'g,46,w4 now default' f
> ... all good.

It sure sounds like you're assembling a scalar and eval-ing it, but
who's to say. (q) works fine in this toy example.

	% () { eval "print -rC1 -- $@" } a 'b c' d 'e f g'
	a
	b
	c
	d
	e
	f
	g
	% () { eval "print -rC1 -- ${(q)@}" } a 'b c' d 'e f g'
	a
	b c
	d
	e f g

--
vq

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-10  0:51       ` Ray Andrews
  2021-02-10  1:46         ` Lawrence Velázquez
@ 2021-02-10  1:52         ` Greg Klanderman
  2021-02-10  2:29           ` Ray Andrews
  2021-02-10 15:18           ` Ray Andrews
  1 sibling, 2 replies; 23+ messages in thread
From: Greg Klanderman @ 2021-02-10  1:52 UTC (permalink / raw)
  To: zsh-users

>>>>> On February 9, 2021 Ray Andrews <rayandrews@eastlink.ca> wrote:

> When a function argument will end up making
> an argument to grep, and the argument to grep must have single quotes, but the
> single
> quotes typed in the function argument are stripped off. What's the solution?

You've gone wrong thinking 'the argument to grep must have single
quotes'.  You need single quotes to get the filename into the
function/script as a single argument initially, but if you keep it in
an array value, you can then expand the array in the grep invocation
preserving the arguments using the "${array[@]}" syntax.

consider

grep_wrapper () {
  grepargs=()
  while [[ $# -gt 0 ]] ; do
    arg="$1"
    shift
    case $arg in
      --foo* )
          echo "do something else with $arg"
          ;;
      * )
          grepargs+=( "$arg" )
          ;;
    esac
  done
  grep --color=always -i -- "${grepargs[@]}"
}

based on 'unsetopt shwordsplit' and some other options, you can get
away without some of the double quoting and {}.  but if you want to be able
to preserve the empty string, "", as an argument you are pretty much
stuck needing double quotes.

Greg


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-10  1:46         ` Lawrence Velázquez
@ 2021-02-10  2:25           ` Ray Andrews
  2021-02-10  2:52             ` Lawrence Velázquez
  0 siblings, 1 reply; 23+ messages in thread
From: Ray Andrews @ 2021-02-10  2:25 UTC (permalink / raw)
  To: zsh-users

On 2021-02-09 5:46 p.m., Lawrence Velázquez wrote:

> ... which youhave already decided is an ulcer and cannot possibly be 
> anything
> other than an ulcer.
It would take far too long to explain the whole show.  If you have the 
time and interest
contact me privately and I'll show you what I'm up to.  But I already 
waste far too much
of the list's time.

> It sure sounds like you're assembling a scalar and eval-ing it, 

That's exactly what I'm doing. But far more.

> % () { eval "print -rC1 -- ${(q)@}" } a 'b c' d 'e f g'
> 	a
> 	b c
> 	d
> 	e f g
>
>
Thing is that if those args were going to grep and they were filenames 
you'd end up with:

$ grep [some search string] a b c d e f g
... whereas your filenames are 'a'   'b c'   d   and   'e  f  g'.
The single quotes must be preserved or the spaces backslashed.  But as  
I just posted, double quoting the whole filespec:

"a 'b c' d 'e f g' "
... appears to be working fine.  grep looks in four files not seven.   
Seems the double quotes preserve the single quotes.




^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-10  1:52         ` Greg Klanderman
@ 2021-02-10  2:29           ` Ray Andrews
  2021-02-10 15:18           ` Ray Andrews
  1 sibling, 0 replies; 23+ messages in thread
From: Ray Andrews @ 2021-02-10  2:29 UTC (permalink / raw)
  To: zsh-users

On 2021-02-09 5:52 p.m., Greg Klanderman wrote:
> grep --color=always -i -- "${grepargs[@]}"

I'll look at that all when I have time Greg but it sure looks like it's 
gonna work.  Thanks.



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-10  2:25           ` Ray Andrews
@ 2021-02-10  2:52             ` Lawrence Velázquez
  0 siblings, 0 replies; 23+ messages in thread
From: Lawrence Velázquez @ 2021-02-10  2:52 UTC (permalink / raw)
  To: Ray Andrews; +Cc: zsh-users

> On Feb 9, 2021, at 9:25 PM, Ray Andrews <rayandrews@eastlink.ca> wrote:
> 
> On 2021-02-09 5:46 p.m., Lawrence Velázquez wrote:
> 
>> ... which youhave already decided is an ulcer and cannot possibly be anything
>> other than an ulcer.
> It would take far too long to explain the whole show.  If you have the time and interest
> contact me privately and I'll show you what I'm up to.  But I already waste far too much
> of the list's time.

Au contraire.

https://www.mikeash.com/getting_answers.html#provide

>> % () { eval "print -rC1 -- ${(q)@}" } a 'b c' d 'e f g'
>> 	a
>> 	b c
>> 	d
>> 	e f g
>> 
>> 
> Thing is that if those args were going to grep and they were filenames you'd end up with:
> 
> $ grep [some search string] a b c d e f g

No. This has nothing to do with grep and everything to do with how
you assemble the eval argument.

% () { emulate -L zsh && eval "grep ${(q)@}" } pattern 'file 1' file2 'file the third'
grep: file 1: No such file or directory
grep: file2: No such file or directory
grep: file the third: No such file or directory

--
vq

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-10  1:52         ` Greg Klanderman
  2021-02-10  2:29           ` Ray Andrews
@ 2021-02-10 15:18           ` Ray Andrews
  2021-02-10 15:47             ` Peter Stephenson
  2021-02-10 16:28             ` Lawrence Velázquez
  1 sibling, 2 replies; 23+ messages in thread
From: Ray Andrews @ 2021-02-10 15:18 UTC (permalink / raw)
  To: zsh-users

On 2021-02-09 5:52 p.m., Greg Klanderman wrote:

     It works Greg, but it misses the crux of my problem which is that 
all my wrappers run everything thru 'eval'
as below (simplified from your original):

grep_wrapper ()
{
   grepargs=()
   sstring=
   while [[ $# -gt 0 ]] ; do
     arg="$1"
     shift
       grepargs+=( "$arg" )                            # This is what 
Peter was saying.
   done
#  grep --color=always -i -- "${grepargs[@]}"         # Works fine but ...
   sstring="grep --color=always -i -- ${grepargs[@]}"  # I need to save 
to a scalar ...
   print -rS "$sstring"                                # Write to 
history ...
   eval "$sstring"                                     # And 'eval'.

   print -r "\n$sstring"
}

9 /aWorking/Zsh/Source/Wk 4 $ . test; grep_wrapper 'on the current' 
'i,2,light edit' 'i,1,old stable'
grep: the: No such file or directory
grep: current: No such file or directory
grep: i,2,light: No such file or directory
grep: edit: No such file or directory
grep: i,1,old: No such file or directory
grep: stable: No such file or directory

grep --color=always -i -- on the current i,2,light edit i,1,old stable

     ... as before the quotes are stripped if I do it my way.  But as I 
discovered last night:

9 /aWorking/Zsh/Source/Wk 4 $ . test; grep_wrapper "'on the current' 
'i,2,light edit' 'i,1,old stable'"
i,2,light edit:Find any command named 'mtr*' on the current path.
i,1,old stable:Find any command named 'mtr*' on the current path.

grep --color=always -i -- 'on the current' 'i,2,light edit' 'i,1,old stable'

     ... by simply double quoting the argument string, the single quotes 
are preserved and 'eval' works.

She is NOT being unreasonable.   Just do it her way and everything will 
be fine.
A lesson for life.



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-10 15:18           ` Ray Andrews
@ 2021-02-10 15:47             ` Peter Stephenson
  2021-02-10 16:19               ` Ray Andrews
  2021-02-10 16:28             ` Lawrence Velázquez
  1 sibling, 1 reply; 23+ messages in thread
From: Peter Stephenson @ 2021-02-10 15:47 UTC (permalink / raw)
  To: Ray Andrews, zsh-users


> On 10 February 2021 at 15:18 Ray Andrews <rayandrews@eastlink.ca> wrote:
>    sstring="grep --color=always -i -- ${grepargs[@]}"  # I need to save 
> to a scalar ...
>    print -rS "$sstring"                                # Write to 
> history ...
>    eval "$sstring"                                     # And 'eval'.

Don't turn it into a string here.

fullargs=(grep --color=always -i -- "${grepargs[@]}")
print -rS "$fullargs"
"${fullargs[@]}"

No eval needed, the arguments are now exactly the correct command arguments.

Actually, the

"${stuff[@]}"

is only needed to preserve empty arguments.  It's a good habit to get into,
but you can think about it more simply as just

$stuff

i.e. a set of array elements that turn into a set of command arguments.

pws


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-10 15:47             ` Peter Stephenson
@ 2021-02-10 16:19               ` Ray Andrews
  2021-02-10 16:29                 ` Peter Stephenson
  2021-02-10 18:08                 ` Bart Schaefer
  0 siblings, 2 replies; 23+ messages in thread
From: Ray Andrews @ 2021-02-10 16:19 UTC (permalink / raw)
  To: zsh-users

On 2021-02-10 7:47 a.m., Peter Stephenson wrote:
>
> No eval needed, the arguments are now exactly the correct command arguments.
>
If you look at this one case indeed no eval is needed, but in the 
broader context of the way all
my functions work, the eval is unavoidable.  Or is it?  Maybe not.




^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-10 15:18           ` Ray Andrews
  2021-02-10 15:47             ` Peter Stephenson
@ 2021-02-10 16:28             ` Lawrence Velázquez
  1 sibling, 0 replies; 23+ messages in thread
From: Lawrence Velázquez @ 2021-02-10 16:28 UTC (permalink / raw)
  To: Ray Andrews; +Cc: zsh-users

> On Feb 10, 2021, at 10:18 AM, Ray Andrews <rayandrews@eastlink.ca> wrote:
> 
> She is NOT being unreasonable.   Just do it her way and everything will be fine.
> A lesson for life.

I'd appreciate it if you kept these "women, AMIRITE?" remarks to
yourself, thanks.

vq

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-10 16:19               ` Ray Andrews
@ 2021-02-10 16:29                 ` Peter Stephenson
  2021-02-10 20:53                   ` Ray Andrews
  2021-02-10 18:08                 ` Bart Schaefer
  1 sibling, 1 reply; 23+ messages in thread
From: Peter Stephenson @ 2021-02-10 16:29 UTC (permalink / raw)
  To: zsh-users

> On 10 February 2021 at 16:19 Ray Andrews <rayandrews@eastlink.ca> wrote:
> On 2021-02-10 7:47 a.m., Peter Stephenson wrote:
> >
> > No eval needed, the arguments are now exactly the correct command arguments.
> >
> If you look at this one case indeed no eval is needed, but in the 
> broader context of the way all
> my functions work, the eval is unavoidable.  Or is it?  Maybe not.

As always, that depends what you're actually doing, which is a superset of
what you're telling us you're doing, but in general it shouldn't be a problem
--- unless you know you need an extra set of expansions, it's possible to
prepare the arguments you need in the array to be executed as a command
line.

What I mean is, the cases where this *wouldn't* work would be like this...

fullargs=(some stuff '$to_be_expanded_later')

So somewhere down the line you're going to assign to to_be_expanded_later,
and you want that to be expanded when you execute the command line.
*Now* you need the extra eval.  But if you're not doing anything like
that, you've just plain old command line arguments and no eval is needed.

pws


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-10 16:19               ` Ray Andrews
  2021-02-10 16:29                 ` Peter Stephenson
@ 2021-02-10 18:08                 ` Bart Schaefer
  2021-02-10 20:56                   ` Ray Andrews
  1 sibling, 1 reply; 23+ messages in thread
From: Bart Schaefer @ 2021-02-10 18:08 UTC (permalink / raw)
  To: Ray Andrews; +Cc: Zsh Users

On Wed, Feb 10, 2021 at 8:19 AM Ray Andrews <rayandrews@eastlink.ca> wrote:
>
> On 2021-02-10 7:47 a.m., Peter Stephenson wrote:
> >
> > No eval needed, the arguments are now exactly the correct command arguments.
> >
> If you look at this one case indeed no eval is needed, but in the
> broader context of the way all
> my functions work, the eval is unavoidable.  Or is it?  Maybe not.

Even if you do need "eval", you should still use an array.  That is, instead of

sstring="grep --color=always -i -- ${grepargs[@]}"
eval "$sstring"

use

sarray=(grep --color=always -i -- "${grepargs[@]}")
eval "${(@q)sarray}"

Using (@q) causes each individual array element to be quoted
separately.  The double quotes then expand it in the manner of
"${sarray[@]}".


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-10 16:29                 ` Peter Stephenson
@ 2021-02-10 20:53                   ` Ray Andrews
  2021-02-10 22:14                     ` Bart Schaefer
  0 siblings, 1 reply; 23+ messages in thread
From: Ray Andrews @ 2021-02-10 20:53 UTC (permalink / raw)
  To: zsh-users

On 2021-02-10 8:29 a.m., Peter Stephenson wrote:
>
> As always, that depends what you're actually doing, which is a superset of
> what you're telling us you're doing,
It's hard to put it briefly and still accurately.  I went down a certain 
path when I first
got involved and it might not have been the right path nevertheless it 
has a certain
power.  My wrappers evolve and evolve with more and more filtering and 
coloring
and columnizing and massaging and end up with some monstrous actual command
strings to execute.  By being able to recall the actual command, I can 
edit it to find
some bug very quickly.  My function assembled: " grep-i -- arg arg " 
when what was
wanted was: " grep -i -- arg arg " . Once I know where the bug is, I can 
figure out
where it came from in my function very quickly.   So I assemble my 
string, save it
to history (optionally) and then eval it to fire it off.  Up arrow, and 
voila!  I have the
guts of what my function did, available to tweak.  So:

9 /aWorking/Zsh/Source/Wk 3 $ l ,H l,*

LISTING of "l,*": all file types, INsensitive. Sorting upside down by: 
Mod. Time:

  11434 [2021-01-07--08:49] l,6,NO H
  10516 [2021-01-07--08:49] l,4,BUG and case now insensitive
...
  15988 [2021-02-03--20:06] l,51,colorize all matches if leading wildcard
  15614 [2021-02-04--16:34] l,52,bug with totals

Items found: 52
Total bytes in this directory: 3.5M
Total including subdirs: 16M

... and how did that actually happen?  " ,H " orders a write to history 
so up arrow and:

9 /aWorking/Zsh/Source/Wk 3 $ ls -AFrGgdt --time-style='+[%F--%H:%M]' 
--group-directories-first --color=always  (#i)l,* 2> /dev/null   | sed 
-r "s|^(.{10} {1,2}[[:digit:]]{1,2} )| |"  | egrep -v '^total' | egrep 
-i --color=always "^|] l,*"                      | sed -r 
"s/\x1b\[01;31m\x1b\[K\] /\] \x1b\[01;31m\x1b\[K/g"

... that's the actual guts of the thing.  No, I'm not insane, I just 
like color, prefer to remove all the permissions stuff since it it 
irrelevant to me, etc.  But the whole show requires the whole command to 
exist as a string so it can be saved and thus it needs 'eval' to fire it 
off ... unless I'm mistaken.

If that makes any sense.  It all works quite fine but there are these 
quoting issues now and then.






^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-10 18:08                 ` Bart Schaefer
@ 2021-02-10 20:56                   ` Ray Andrews
  0 siblings, 0 replies; 23+ messages in thread
From: Ray Andrews @ 2021-02-10 20:56 UTC (permalink / raw)
  To: zsh-users

On 2021-02-10 10:08 a.m., Bart Schaefer wrote:
> sarray=(grep --color=always -i -- "${grepargs[@]}")
> eval "${(@q)sarray}"
>
> Using (@q) causes each individual array element to be quoted
> separately.  The double quotes then expand it in the manner of
> "${sarray[@]}".
>
That looks like exactly what I've been wanting.  Test later.



^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-10 20:53                   ` Ray Andrews
@ 2021-02-10 22:14                     ` Bart Schaefer
  2021-02-11 16:31                       ` Ray Andrews
  0 siblings, 1 reply; 23+ messages in thread
From: Bart Schaefer @ 2021-02-10 22:14 UTC (permalink / raw)
  To: Ray Andrews; +Cc: Zsh Users

On Wed, Feb 10, 2021 at 12:54 PM Ray Andrews <rayandrews@eastlink.ca> wrote:
>
> [...] So I assemble my string, save it
> to history (optionally) and then eval it to fire it off.
> [...] But the whole show requires the whole command to
> exist as a string so it can be saved and thus it needs 'eval' to fire it
> off ... unless I'm mistaken.

Following on my last message, it should work fine to do
print -sr -- "${(@q)sarray}"

You probably want (@q-) there, to minimize the number of quoted
things, or (@q+) if you use a lot of unicode characters or control
strings.

Only "print -S" requires a single string argument.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-10 22:14                     ` Bart Schaefer
@ 2021-02-11 16:31                       ` Ray Andrews
  2021-02-11 17:19                         ` Lawrence Velázquez
  0 siblings, 1 reply; 23+ messages in thread
From: Ray Andrews @ 2021-02-11 16:31 UTC (permalink / raw)
  To: zsh-users

On 2021-02-10 2:14 p.m., Bart Schaefer wrote:
>
> You probably want (@q-) there, to minimize the number of quoted
> things, or (@q+) if you use a lot of unicode characters or control
> strings.

Seems to be working fine:


grep_wrapper ()
{
   grepargs=()
   sstring=
   while [[ $# -gt 0 ]] ; do
     arg="$1"
     shift
       grepargs+=( "$arg" )
   done
   sarray=(grep --color=always -i -- "${grepargs[@]}")

   print -sr -- "${(@q)sarray}"
   echo "\nwhat should be going to history:"
   print -r -- "${(@q)sarray}"

   echo "\neval:"
   eval "${(@q)sarray}"
}

     Test run:

9 /aWorking/Zsh/Source/Wk 3 $ . test; grep_wrapper 'on the current' 
'i,2,light edit' 'i,1,old stable'

what should be going to history:
grep --color=always -i -- on\ the\ current i,2,light\ edit i,1,old\ stable

eval:
i,2,light edit:Find any command named 'mtr*' on the current path.
i,1,old stable:Find any command named 'mtr*' on the current path.

     Up arrow to recall and then re-execute:

9 /aWorking/Zsh/Source/Wk 3 $ grep --color=always -i -- on\ the\ current 
i,2,light\ edit i,1,old\ stable
i,2,light edit:Find any command named 'mtr*' on the current path.
i,1,old stable:Find any command named 'mtr*' on the current path.
--------------------------------------------------------------------------------------------------------------------

So, the single quotes might be protected by double quoting as I had it 
before,
or we can use the magic of ' (q) ' to protect the spaces with 
backslashes even
though the single quotes themselves are gone.  Or, using ' (q-) ':

9 /aWorking/Zsh/Source/Wk 3 $ . test; grep_wrapper 'on the current' 
'i,2,light edit' 'i,1,old stable'

what should be going to history:
grep --color=always -i -- 'on the current' 'i,2,light edit' 'i,1,old stable'

eval:
i,2,light edit:Find any command named 'mtr*' on the current path.
i,1,old stable:Find any command named 'mtr*' on the current path.

     Up arrow and re-execute:

9 /aWorking/Zsh/Source/Wk 3 $ grep --color=always -i -- 'on the current' 
'i,2,light edit' 'i,1,old stable'
i,2,light edit:Find any command named 'mtr*' on the current path.
i,1,old stable:Find any command named 'mtr*' on the current path.
-------------------------------------------------------------------------------------------------------

Seems cleaner, the single quotes are themselves protected or replaced so 
that
it not only runs right, it looks right; on recall it is  visually 
exactly the same.  And is it not
intuitive that, since single quotes already protect their string, if you 
add protection for the
single quotes themselves, you then have a perfectly protected string?  
It can be
passed from one function to the next unchanged.  This is the holy grail 
for me.
Any gotchas?  Or is that robust?  Can I use it everywhere?  Seems 
right.  The array
separates the arguments even if the might look like they run together in 
a string.

Thanks all.




^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-11 16:31                       ` Ray Andrews
@ 2021-02-11 17:19                         ` Lawrence Velázquez
  2021-02-11 19:48                           ` Ray Andrews
  0 siblings, 1 reply; 23+ messages in thread
From: Lawrence Velázquez @ 2021-02-11 17:19 UTC (permalink / raw)
  To: Ray Andrews; +Cc: zsh-users

> On Feb 11, 2021, at 11:31 AM, Ray Andrews <rayandrews@eastlink.ca> wrote:
> 
>   while [[ $# -gt 0 ]] ; do
>     arg="$1"
>     shift
>       grepargs+=( "$arg" )
>   done

Why are you still accreting grepargs like this? Peter has already
shown you how to do this.

	grepargs=("$@")

Unless your actual code actually modifies the args before adding
them to the array?

> Seems cleaner, the single quotes are themselves protected or replaced so that
> it not only runs right, it looks right; on recall it is  visually exactly the same.

The command saved to history is correct, but it is not always exactly
what you entered.

	% grep_wrapper on\ the\ current i,2,light\ edit i,1,old\ stable 

	what should be going to history:
	grep --color=always -i -- 'on the current' 'i,2,light edit' 'i,1,old stable'

	[...]

	% pat='on the current' foo='i,2,light edit' bar='i,1,old stable'
	% grep_wrapper $pat $foo $bar

	what should be going to history:
	grep --color=always -i -- 'on the current' 'i,2,light edit' 'i,1,old stable'

	[...]

A ${(q-)foo} expansion basically re-quotes the value of foo so
it works correctly with eval, in whatever way is requested. It
doesn't know the value's origins.

> And is it not intuitive that, since single quotes already
> protect their string, if you add protection for the single
> quotes themselves, you then have a perfectly protected string?

That's not how quoting works. Quote levels don't nest to produce
some kind of super-quoting. You're misinterpreting the results of
your experimentation.

	% foo='a b c'
	% print -r 'protected: $foo'
	protected: $foo
	% print -r "'not protected: $foo'"
	'not protected: a b c'

The double quotes do protect the single quotes from being interpreted
by the shell, but they also permit expansions.

vq

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: protect spaces and/or globs
  2021-02-11 17:19                         ` Lawrence Velázquez
@ 2021-02-11 19:48                           ` Ray Andrews
  0 siblings, 0 replies; 23+ messages in thread
From: Ray Andrews @ 2021-02-11 19:48 UTC (permalink / raw)
  To: zsh-users

On 2021-02-11 9:19 a.m., Lawrence Velázquez wrote:
>
> Why are you still accreting grepargs like this? Peter has already
> shown you how to do this.
>
> 	grepargs=("$@")
>
> Unless your actual code actually modifies the args before adding
> them to the array?
Not modified but the ordering is different so I hafta grab them one at a 
time.
Good point tho, all else equal I see that Peter's method is better.
> 	[...]
>
> 	% pat='on the current' foo='i,2,light edit' bar='i,1,old stable'
> 	% grep_wrapper $pat $foo $bar
>
> 	what should be going to history:
> 	grep --color=always -i -- 'on the current' 'i,2,light edit' 'i,1,old stable'
Yes, point made.  I know that if I want something expanded I don't 
single quote it. But indeed
I shouldn't say 'exactly as typed' because I know that variables will be 
expanded.

> 	[...]
>
> A ${(q-)foo} expansion basically re-quotes the value of foo so
> it works correctly with eval, in whatever way is requested. It
> doesn't know the value's origins.
That's a subtle but important point.  I could think of it as 
'protection' but then
how did the variable expand?  As you say it must be seen as re-quoting.  
Thanks
for catching it.
> That's not how quoting works. Quote levels don't nest to produce
> some kind of super-quoting. You're misinterpreting the results of
> your experimentation.
>
> 	% foo='a b c'
> 	% print -r 'protected: $foo'
> 	protected: $foo
> 	% print -r "'not protected: $foo'"
> 	'not protected: a b c'
>
> The double quotes do protect the single quotes from being interpreted
> by the shell, but they also permit expansions.
That is a critical point.  You know, it is so easy to think you've 'got 
it' when you don't.
I'm going to take the above and write it to a sticky note a stick it to 
my desk.  Very
insightful of you to realize that I'm not seeing things right, many thanks.



^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2021-02-11 19:49 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-09 20:42 protect spaces and/or globs Ray Andrews
2021-02-09 21:05 ` Lawrence Velázquez
2021-02-09 21:08 ` Peter Stephenson
2021-02-09 23:45   ` Ray Andrews
2021-02-10  0:22     ` Lawrence Velázquez
2021-02-10  0:51       ` Ray Andrews
2021-02-10  1:46         ` Lawrence Velázquez
2021-02-10  2:25           ` Ray Andrews
2021-02-10  2:52             ` Lawrence Velázquez
2021-02-10  1:52         ` Greg Klanderman
2021-02-10  2:29           ` Ray Andrews
2021-02-10 15:18           ` Ray Andrews
2021-02-10 15:47             ` Peter Stephenson
2021-02-10 16:19               ` Ray Andrews
2021-02-10 16:29                 ` Peter Stephenson
2021-02-10 20:53                   ` Ray Andrews
2021-02-10 22:14                     ` Bart Schaefer
2021-02-11 16:31                       ` Ray Andrews
2021-02-11 17:19                         ` Lawrence Velázquez
2021-02-11 19:48                           ` Ray Andrews
2021-02-10 18:08                 ` Bart Schaefer
2021-02-10 20:56                   ` Ray Andrews
2021-02-10 16:28             ` Lawrence Velázquez

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).