From 912421f1cb61fca530fb501b9e6a904dc21e44d6 Mon Sep 17 00:00:00 2001 From: Mahmoud Al-Qudsi <mqudsi@neosmart.net> Date: Thu, 5 Sep 2019 22:40:31 -0500 Subject: [PATCH] Switch away from `awk` for `__fish_print_hostnames` By not manipulating each line or even each file at a time, we can go back to `string` and piece together a pipeline that will execute significantly faster than shelling out to `awk` will. This also removes one of the few dependencies on `awk` in the codebase. With this change, `__fish_print_hostnames` now finishes ~80% faster than it used to a few commits back. --- share/functions/__fish_print_hostnames.fish | 27 +++++++++------------ 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/share/functions/__fish_print_hostnames.fish b/share/functions/__fish_print_hostnames.fish index c9a269b46..1034b49a5 100644 --- a/share/functions/__fish_print_hostnames.fish +++ b/share/functions/__fish_print_hostnames.fish @@ -121,22 +121,17 @@ function __fish_print_hostnames -d "Print a list of known hostnames" read -z <$file end end | - # Ignore hosts that are hashed, commented or @-marked and strip the key. - awk '$1 !~ /[|#@]/ { - n=split($1, entries, ",") - for (i=1; i<=n; i++) { - # Ignore negated/wildcarded hosts. - if (!match(entry=entries[i], "[!*?]")) { - # Extract hosts with custom port. - if (substr(entry, 1, 1) == "[") { - if (pos=match(entry, "]:.*$")) { - entry=substr(entry, 2, pos-2) - } - } - print entry - } - } - }' + # Ignore hosts that are hashed, commented or @-marked and strip the key + # Handle multiple comma-separated hostnames sharing a key, too. + # + # This one regex does everything we need, finding all matches including comma-separated + # values, but fish does not let us print only a capturing group without the entire match, + # and we can't use `string replace` instead (because CSV then fails). + # string match -ar "(?:^|,)(?![@|*!])\[?([^ ,:\]]+)\]?" + # + # Instead, manually piece together the regular expressions + string match -v -r '^\s*[!*|@#]' | string replace -r '^\s*(\S+) .*' '$1' | + string split ',' | string replace -r '\[?([^:\]]+).*' '$1' return 0 end