Skip to content

Instantly share code, notes, and snippets.

@andrewgho
Last active October 27, 2022 17:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewgho/755bcd2555bcf67d4bcfd80d2fe5ca74 to your computer and use it in GitHub Desktop.
Save andrewgho/755bcd2555bcf67d4bcfd80d2fe5ca74 to your computer and use it in GitHub Desktop.
bash in-process string substitution with one capturing group
# Bash parameter expansion syntax for ${parameter/match/replacement}:
# https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
#
# Bash pattern matching syntax:
# https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html
#
# Bash conditional [[ string =~ pattern ]] and $BASH_REMATCH syntax:
# https://www.gnu.org/software/bash/manual/html_node/Conditional-Constructs.html
#
# Recipe to do a string replace with capturing:
# https://stackoverflow.com/a/22261643
# String substitution with limited support for regex and capturing match
sub() {
local string="$1"
local pattern="$2"
local replacement="$3"
# If no match, output original string and return false
[[ $string =~ $pattern ]] || { echo "$string" && return 1; }
# Save the first captured string match, if any
local match=${BASH_REMATCH[1]}
# Expand replacement token $1 with captured string
replacement=${replacement/\$1/$match}
# Change regex start anchor to parameter expansion start anchor
pattern=${pattern/#^/#}
# Update pattern to replace capturing match with literal matched value
pattern=${pattern/\(*\)/$match}
# Replace the entire literal matched pattern with expanded replacement
echo ${string/$pattern/$replacement}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment