Serious Shell Programming
  • Introduction
  • Acknowledgements
  • Basics
    • Strings
      • Single-Quotes
      • Double-Quotes
      • Unquoted Strings
      • Compound Strings
    • Here Documents
      • Here Doc
      • Indented Here Doc
      • Literal Here Doc
      • In-Memory Here Doc
    • Conditionals
      • Built-in test
      • Parameter Conditionals
      • Parameter test
    • Regex
      • grep
      • awk
      • pcre
    • Control Flow
      • Binary Operators
      • if-elif-else
      • case Statement
      • for Loop
      • while Loop
      • Functions
  • shellcheck
    • Introduction
    • Bad Advice
  • Style
    • awk
    • case
    • Redirection
    • Comments
    • trap
  • String Functions
    • substr
    • sprintf
    • replace
    • replaceall
    • replacestart
    • replaceend
    • fnmatch
  • awk
    • Pre-declaring Arrays
    • Sorting Arrays
  • Know Your limits
    • Arguments
    • Environment Variables
    • Solutions
Powered by GitBook
On this page

Was this helpful?

  1. String Functions

replaceall

Unlike Bourne Again Shell (bash), POSIX shell does not have a native find/replace function for replacing all occurrences of a pattern in a given string with another. Below is an implementation written in native POSIX shell that is:

  • Faster than piping to awk, sed, perl, python, ruby, or other langauge

  • Compatible with bash and all other POSIX-compliant shells

  • Optimized to use ${parameter//pattern[/string]} when bash is detected

 1 #!/bin/sh
 2 if [ "$BASH_VERSION" ]; then
 3     replaceall() # $var_to_get $find $replace [$var_to_set]
 4     {
 5         eval ${4:-$1}=\"\${$1//\$2${3:+/\$3}}\"
 6     }
 7 else
 8     # NB: On FreeBSD, sh(1) runs this faster than bash(1) runs the above
 9     replaceall() # $var_to_get $find $replace [$var_to_set]
10     {
11         eval local __left= __right=\"\$$1\" || return
12         while :; do
13             case "$__right" in *$2*)
14                 __left="$__left${__right%%$2*}$3"
15                 __right="${__right#*$2}"
16                 continue
17             esac
18             break
19         done
20         __left="$__left${__right#*$2}"
21         eval ${4:-$1}=\"\$__left\"
22     }
23 fi
24 eval echo \"before=[\$$1]\"
25 replaceall "$@"
26 eval echo \" after=[\$${4:-$1}]\"
PreviousreplaceNextreplacestart

Last updated 5 years ago

Was this helpful?