* unmatched ' @ 2018-03-09 17:50 Ray Andrews 2018-03-09 20:23 ` Bart Schaefer 0 siblings, 1 reply; 7+ messages in thread From: Ray Andrews @ 2018-03-09 17:50 UTC (permalink / raw) To: Zsh Users I have a function that lists all directories matching a nesting set of strings: $ c etc systemd system ... the list is culled by matching each string in turn. It works fine except that: $ c etc (eval):1: unmatched ' ... but that's the one and only directory that throws that error. I've tested dozens of directories and combinations and all are fine except 'etc'. I suspect this abomination: /etc/DSHR's Blog: Using the official Linux overlayfs_files ... God knows why that's permitted, but I'm thinking that the single quote is doing the obvious thing as far as 'eval' in concerned. Can I prevent that? Or, if it must be an error, can I get eval to ignore it somehow? The offending line is this: baz=(`eval print -l $bar $grepstring`) ... I want to sent the output of printing '$bar' after it's been piped through the chain of greps that are built up and saved in the '$grepstring' variable, and save that filtered and colored result in '$baz'. Apart from the above, it works perfectly. I'm betting there's a flag ${(flag)bar} that fixes it, i.e. forcing " DSHR's " to be literal. Otherwise I will excoriate the offending directories. Work of the Devil. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: unmatched ' 2018-03-09 17:50 unmatched ' Ray Andrews @ 2018-03-09 20:23 ` Bart Schaefer 2018-03-09 22:45 ` Ray Andrews 0 siblings, 1 reply; 7+ messages in thread From: Bart Schaefer @ 2018-03-09 20:23 UTC (permalink / raw) To: Ray Andrews; +Cc: Zsh Users On Fri, Mar 9, 2018 at 9:50 AM, Ray Andrews <rayandrews@eastlink.ca> wrote: > > $ c etc > > (eval):1: unmatched ' > > I suspect this abomination: > > /etc/DSHR's Blog: Using the official Linux overlayfs_files > > ... God knows why that's permitted, but I'm thinking that the single quote > is doing the obvious thing as far as 'eval' in concerned. Can I prevent > that? Or, if it must be an error, can I get eval to ignore it somehow? The > offending line is this: > > baz=(`eval print -l $bar $grepstring`) You really should never do this with "eval". Consider what happens if the file name is /etc/Why you should never `rm -rf /` (Obligatory warning: DO NOT TRY THAT AT HOME.) Why are you putting stuff like that file in /etc/ in the first place? It's not meant to be a scratch or documentation directory, it's supposed to contain system-wide configuration files. https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard > ... I want to sent the output of printing '$bar' after it's been piped > through the chain of greps that are built up and saved in the '$grepstring' If $bar is a file name with spaces in it, `eval print -l $bar` is going to split the name up on the spaces and write one "word" of the file name on each line. Is that actually what you intend? Otherwise unless $bar is an array, you don't need the -l option of print, because you're always printing just one line anyway. If $bar is a file name that begins with a hyphen, "print" is going to try to interpret that as options. Based on your description there must be a leading "|" in $grepstring. Don't do that. Assuming you've carefully sanitized $grepstring to avoid gotchas like unintentional `...` or $(...) substitutions, the closest you should ever get to what you're doing is baz=( `print -lr -- "${bar[@]}" | eval "$grepstring"` ) There's probably a better way to do your cascade of greps, too, such as building a file with one pattern per line and running a single "grep -f patternfile", but you haven't provided sufficient context. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: unmatched ' 2018-03-09 20:23 ` Bart Schaefer @ 2018-03-09 22:45 ` Ray Andrews 2018-03-09 23:12 ` Ray Andrews 2018-03-10 3:20 ` Aaron Schrab 0 siblings, 2 replies; 7+ messages in thread From: Ray Andrews @ 2018-03-09 22:45 UTC (permalink / raw) To: zsh-users On 09/03/18 12:23 PM, Bart Schaefer wrote: > You really should never do this with "eval". Consider what happens if the > file name is /etc/Why you should never `rm -rf /` > > (Obligatory warning: DO NOT TRY THAT AT HOME.) I probably have a lot of improper constructions here, I use the first thing that seems to work, and later I repent of various sins as they become apparent. How would I best do that sort of thing? > Why are you putting stuff like that file in /etc/ in the first place? Heck, not me! That's stock Debian, I'd not create a directory like that on pain of damnation. Debian should not allow it either, IMHO. > If $bar is a file name with spaces in it, $bar will start with a list of directories as originally output by 'find', so whatever my code, it has to handle whatever 'find' might find. > Based on your description there must be a leading "|" in $grepstring. > Don't do that. Yeah: ccolor=33 # Start with yellow, then blue, magenta, cyan. for file in "$@"; do # We colorize the already selected lines here: grepstring="$grepstring | GREP_COLOR='01;'"$ccolor" grep $wwild $ccase --color=always \"$file\"" (( ccolor++ )) # Next color. done ... so I'm filtering and colorizing however many arguments there are to the command, so each iteration must (?) begin with the pipe. And the final string: bar=(`eval "find -H -O3 / -warn -type d -ipath \"*$1*\"" $grepstring`) > Assuming you've carefully sanitized $grepstring to avoid gotchas like > unintentional `...` or $(...) substitutions, the closest you should > ever get to what you're doing is > > baz=( `print -lr -- "${bar[@]}" | eval "$grepstring"` ) > > There's probably a better way to do your cascade of greps, too, such > as building a file with one pattern per line and running a single > "grep -f patternfile", but you haven't provided sufficient context. > The $grepstring itself can't have any surprises (famous last words) but the entire construction is of course suspect. I see you're shrinking the target of eval to the minimum, that seems sensible on first principals but I can't think of a way to get the first pipe outside of $grepstring. The thing is just to turn a string into a command because the only way I know to create flexible commands is by way of strings. Anyway, is there no way of putting a global protection on nasty characters inside the list of directories? I'm sure I did read about that, but there's so much to remember. BTW I started doing this sort of cascading colorization with a very similar function I use to explore the history. I can refine the search with as many strings as I want, and they all show up with different colors, which is even useful, not just eye candy. The final array gets fed to Sebastian's 'n_list' for selection. Quite indispensable to me. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: unmatched ' 2018-03-09 22:45 ` Ray Andrews @ 2018-03-09 23:12 ` Ray Andrews 2018-03-10 3:20 ` Aaron Schrab 1 sibling, 0 replies; 7+ messages in thread From: Ray Andrews @ 2018-03-09 23:12 UTC (permalink / raw) To: zsh-users On 09/03/18 02:45 PM, Ray Andrews wrote: > baz=( `print -lr -- "${bar[@]}" | eval "$grepstring"` ) baz=(`eval print -lr -- ${(q)bar} $grepstring`) That works, " (q) " was the thing I was trying to remember. It's in the scrolls, and my Coptic is getting better ;-)) baz=( `print -lr -- "${bar[@]}" eval "$grepstring"` ) << pipe within $grepstring as per previous logic ... didn't work , but maybe there is a better way? ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: unmatched ' 2018-03-09 22:45 ` Ray Andrews 2018-03-09 23:12 ` Ray Andrews @ 2018-03-10 3:20 ` Aaron Schrab 2018-03-10 3:51 ` Ray Andrews 1 sibling, 1 reply; 7+ messages in thread From: Aaron Schrab @ 2018-03-10 3:20 UTC (permalink / raw) To: Ray Andrews; +Cc: zsh-users At 14:45 -0800 09 Mar 2018, Ray Andrews <rayandrews@eastlink.ca> wrote: >>Why are you putting stuff like that file in /etc/ in the first place? > >Heck, not me! That's stock Debian, I'd not create a directory like >that on pain of damnation. Debian should not allow it either, IMHO. No, that file is not included in any Debian package: https://packages.debian.org/search?searchon=contents&keywords=DSHR&mode=filename&suite=stable&arch=any > ccolor=33 # Start with yellow, then blue, magenta, cyan. > for file in "$@"; do > # We colorize the already selected lines here: > grepstring="$grepstring | GREP_COLOR='01;'"$ccolor" grep >$wwild $ccase --color=always \"$file\"" > (( ccolor++ )) # Next color. > done > >... so I'm filtering and colorizing however many arguments there are >to the command, so each iteration must (?) begin with the pipe. And >the final string: Perhaps something like the following? This doesn't include the doing the find(1), instead it's designed to get the text to search on STDIN. It also doesn't use the $wwild or $ccase variables, which I didn't see defined anywhere. But that would be easy to add. No use of eval here. Besides being safer, that also tends to be more readable; although the use of recursion here cuts down on that improvement. Despite having zsh on the #! line, this would work with bash as well. #!/bin/zsh -u # Multi-color grep __mcgrep() { local color=$1; shift local pattern="$1"; shift if [[ $# = 0 ]]; then # No more patterns, just pass through the input cat else __mcgrep $((color + 1)) "$@" fi | GREP_COLOR="01;$color" grep --color=always "$pattern" } # Start with yellow, then blue, magenta, cyan. __mcgrep 33 "$@" ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: unmatched ' 2018-03-10 3:20 ` Aaron Schrab @ 2018-03-10 3:51 ` Ray Andrews 2018-03-10 17:40 ` Ray Andrews 0 siblings, 1 reply; 7+ messages in thread From: Ray Andrews @ 2018-03-10 3:51 UTC (permalink / raw) To: zsh-users On 09/03/18 07:20 PM, Aaron Schrab wrote: > > No, that file is not included in any Debian package: So I've since discovered. God knows where it came from, it's nothing of mine, that's for sure. Apologies to Debian for the suggestion. I've since killed it. > > > > Perhaps something like the following? This doesn't include the doing > the find(1), instead it's designed to get the text to search on > STDIN. It also doesn't use the $wwild or $ccase variables, which I > didn't see defined anywhere. But that would be easy to add. > > No use of eval here. Besides being safer, that also tends to be more > readable; although the use of recursion here cuts down on that > improvement. > > Despite having zsh on the #! line, this would work with bash as well. > > #!/bin/zsh -u > # Multi-color grep > > __mcgrep() { > local color=$1; shift > local pattern="$1"; shift > > if [[ $# = 0 ]]; then > # No more patterns, just pass through the input > cat > else > __mcgrep $((color + 1)) "$@" > fi | > GREP_COLOR="01;$color" grep --color=always "$pattern" > } > > # Start with yellow, then blue, magenta, cyan. > __mcgrep 33 "$@" > Thanks, that's interesting, I'll experiment with it tomorrow. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: unmatched ' 2018-03-10 3:51 ` Ray Andrews @ 2018-03-10 17:40 ` Ray Andrews 0 siblings, 0 replies; 7+ messages in thread From: Ray Andrews @ 2018-03-10 17:40 UTC (permalink / raw) To: zsh-users On 09/03/18 07:51 PM, Ray Andrews wrote: > On 09/03/18 07:20 PM, Aaron Schrab wrote: >> >> #!/bin/zsh -u >> # Multi-color grep >> >> __mcgrep() { >> local color=$1; shift >> local pattern="$1"; shift >> >> if [[ $# = 0 ]]; then >> # No more patterns, just pass through the input >> cat >> else >> __mcgrep $((color + 1)) "$@" >> fi | >> GREP_COLOR="01;$color" grep --color=always "$pattern" >> } >> >> # Start with yellow, then blue, magenta, cyan. >> __mcgrep 33 "$@" >> > Thanks, that's interesting, I'll experiment with it tomorrow. > > > That sure got me thinking. At the very least I can drop 'eval' by looping: for file in "$@"; do foo=( `print -l $foo | GREP_COLOR='01;'$ccolor grep --color=always $file` ) bar=( `print -l $bar | GREP_COLOR='01;'$ccolor grep --color=always $file` ) (( ccolor++ )) # Next color. done ... it seems that one pipe at a time is fine, so rather than create the chain of pipes ahead of time, and try to pass it via $grepstring, if I just loop, everything is fine. My entire function ends up 600 bytes shorter and the whole thing is much easier to read. ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2018-03-10 18:10 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-03-09 17:50 unmatched ' Ray Andrews 2018-03-09 20:23 ` Bart Schaefer 2018-03-09 22:45 ` Ray Andrews 2018-03-09 23:12 ` Ray Andrews 2018-03-10 3:20 ` Aaron Schrab 2018-03-10 3:51 ` Ray Andrews 2018-03-10 17:40 ` Ray Andrews
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).