Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: zsh-ify a bash script

On 21/01/2022 07:48, Daniel Shahaf wrote:
Andreas Kusalananda Kähäri wrote on Thu, Jan 20, 2022 at 12:26:06 +0100:
On Thu, Jan 20, 2022 at 11:40:56AM +0100, Mikael Magnusson wrote:
On 1/20/22, Mikael Magnusson <mikachu@xxxxxxxxx> wrote:
On 1/20/22, Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
On Wed, Jan 19, 2022 at 12:57 PM zzapper <zsh@xxxxxxxxxxxxxx> wrote:
Dumb CLI trick. Wanted to find files containing all of several terms
(dup2, pledge, socketpair, fork), but they could occur anywhere in the
Not zsh any more than the first example, but instead of "grep -l" on
the entire file contents for each term ...

# start by getting the actual occurrences of all the terms:
find . -name '*.c' | xargs egrep
'\<(dup2|pledge|fork|socketpair.*SOCK_STREAM)\>' /dev/null |
# reduce the results to just file names and search terms:
sed -E 's/(^[^:]*\.c:).*\<(dup2|pledge|fork|socketpair)\>.*/\1\2/' |
# make every search term unique per file:
sort -u |
# discard the search terms, leaving only file names:
cut -d : -f 1 |
# count the number of times each file name appears:
uniq -c |
# print names with a count of 4 (the number of search terms):
sed -nE 's/^ *4 //p'

Adjusting this for edge cases where two search terms appear on the
same line is left as an exercise.
This part would probably be fixed by passing -o to grep (didn't test
in the above but):
% echo foobar|grep -E '(foo|bar)'
% echo foobar|grep -oE '(foo|bar)'
I guess this is more or less the same solution,
% grep -Eo '(zsfree|zerr|subst)' Src/**/*.c|sort -u|sed 's/:[^:]*'//|uniq -c|grep -E '^\s+3'
       3 Src/Zle/zle_main.c
       3 Src/builtin.c
       3 Src/exec.c
       3 Src/glob.c
       3 Src/hist.c
       3 Src/jobs.c
       3 Src/signals.c
       3 Src/subst.c
       3 Src/utils.c

Awk-ifying the end of that pipeline... and just playing around with the
grep a bit for fun (changed to use BREs, but still non-standard due to
-w and -o).

grep -Fwo -e zsfree -e zerr -e subst -- Src/**/*.c |
awk -F: '!seen[$0]++ && ++count[$1] == 3 { print $1 }'

This obviously assumes that no pathname contains colons or embedded
Using glob qualifiers:

% has() { <$REPLY grep -q -- "$1" }
% print -raC1 -- **/*.c(e*has zerr*e*has zsfree*e*has subst*)
# looks good just trimmed for my system (Mint)

has() { <$REPLY grep -q -- "$1" }
print -raC1 -- /usr/[sS]rc/**.c(e*has stdio*e*has fcntl*e*has mman*) H

### BTW is there any library of text files we can all guarantee on having for future test purposes?

Messages sorted by: Reverse Date, Date, Thread, Author