ash ${str/find/repl} performance

Ron Yorston rmy at pobox.com
Tue Jul 20 10:04:41 UTC 2021


Alin Mr wrote:

>It seems that bash-like pattern substitution is surprisingly slow.

The relevant code is scanright() and the code around its first call in
subevalvar().  It assumes the search string might contain special
characters.  So for x="root:x:0:0:root:/root:/bin/bash" and ${x//:/|}
it uses fnmatch() to match the pattern against each of these in turn:

   root:x:0:0:root:/root:/bin/bash
   root:x:0:0:root:/root:/bin/bas
   root:x:0:0:root:/root:/bin/ba
   root:x:0:0:root:/root:/bin/b
   ...
   r

When that doesn't work it moves on to:

   oot:x:0:0:root:/root:/bin/bash
   oot:x:0:0:root:/root:/bin/bas
   oot:x:0:0:root:/root:/bin/ba
   oot:x:0:0:root:/root:/bin/b
   ...
   o

Eventually it'll find a match with:

   :x:0:0:root:/root:/bin/bash
   :x:0:0:root:/root:/bin/bas
   :x:0:0:root:/root:/bin/ba
   :x:0:0:root:/root:/bin/b
   ...
   :

After making the replacement it then carries on to find the next match.

It would be possible to use a more efficient approach when the pattern
is known to have no special characters.  But that would require more
code.

Ron


More information about the busybox mailing list