@@ -71,6 +71,16 @@ function cleanup() {
7171 fi
7272}
7373
74+ # Check if Bash supports non-greedy quantifiers (Bash 4.0+)
75+ function supports_bash_regex() {
76+ local bash_major_version=" ${BASH_VERSINFO[0]} "
77+ [[ " $bash_major_version " -ge 4 ]]
78+ }
79+
80+ # endregion
81+ # --------------------------------------------------
82+ # region HTTP functions
83+
7484function http_get() {
7585 local url=" $1 "
7686 # if curl is available, use it, otherwise use wget.
@@ -196,6 +206,53 @@ function get_md_url_regexp() {
196206 echo " \(https:\/\/[a-z0-9.\/]+\/$( get_filename_regexp) \)"
197207}
198208
209+ # Generic regex matching function
210+ # Usage: regex_match "string" "pattern"
211+ # Returns: 0 if matches, 1 if doesn't match
212+ function regex_match() {
213+ local string=" $1 "
214+ local pattern=" $2 "
215+
216+ if supports_bash_regex; then
217+ [[ " $string " =~ $pattern ]]
218+ else
219+ echo " $string " | perl -ne " exit(0) if /$pattern /; exit(1)" 2> /dev/null
220+ fi
221+ }
222+
223+ # Extract capture group from regex match
224+ # Usage: regex_capture "string" "pattern" capture_group_number
225+ # Returns: captured text or empty string
226+ function regex_capture() {
227+ local string=" $1 "
228+ local pattern=" $2 "
229+ local capture_group=" ${3:- 1} "
230+
231+ if supports_bash_regex; then
232+ if [[ " $string " =~ $pattern ]]; then
233+ echo " ${BASH_REMATCH[$capture_group]} "
234+ fi
235+ else
236+ echo " $string " | perl -ne " print \$ $capture_group if /$pattern /"
237+ fi
238+ }
239+
240+ # Extract full match from regex
241+ # Usage: regex_match_text "string" "pattern"
242+ # Returns: matched text or empty string
243+ function regex_match_text() {
244+ local string=" $1 "
245+ local pattern=" $2 "
246+
247+ if supports_bash_regex; then
248+ if [[ " $string " =~ $pattern ]]; then
249+ echo " ${BASH_REMATCH[0]} "
250+ fi
251+ else
252+ echo " $string " | perl -ne " print \$ & if /$pattern /"
253+ fi
254+ }
255+
199256# endregion
200257# --------------------------------------------------
201258# region GitHub API functions
@@ -250,8 +307,9 @@ function fetch_release_info() {
250307function get_repo_name() {
251308 local release_json=" $1 "
252309 local html_url=$( jq -r ' .html_url' " $release_json " )
253- if [[ " $html_url " =~ $REGEXP_NAME_FROM_HTML_URL ]]; then
254- echo " ${BASH_REMATCH[1]} "
310+ local match=$( regex_capture " $html_url " " $REGEXP_NAME_FROM_HTML_URL " 1)
311+ if [[ -n " $match " ]]; then
312+ echo " $match "
255313 fi
256314}
257315
@@ -266,8 +324,8 @@ function find_download_url() {
266324
267325 for name in $( jq -r ' .assets[].name' " $release_json " ) ; do
268326 local lower_name=$( echo " $name " | tr ' [A-Z]' ' [a-z]' )
269- if [[ " $lower_name " =~ $regexp ]] ; then
270- if [[ " $lower_name " =~ $REGEXP_IGNORE_PATTERN ]] ; then
327+ if regex_match " $lower_name " " $regexp " ; then
328+ if regex_match " $lower_name " " $REGEXP_IGNORE_PATTERN " ; then
271329 print_debug " $name ... Ignored"
272330 else
273331 print_debug " $name ... MATCH!"
@@ -292,13 +350,13 @@ function find_download_url() {
292350
293351 jq -r ' .body' " $release_json " | while read -r line; do
294352 lower_line=$( echo " $line " | tr ' [A-Z]' ' [a-z]' )
295- if [[ " $lower_line " =~ $regexp ]]; then
353+ local match=$( regex_match_text " $lower_line " " $regexp " )
354+ if [[ -n " $match " ]]; then
296355 print_debug " $line ... MATCH!"
297356 found=" true"
298- line=" ${BASH_REMATCH[0]} "
299- line=${line: 1}
300- line=${line% ?}
301- echo $line
357+ match=${match: 1}
358+ match=${match% ?}
359+ echo " $match "
302360 else
303361 print_debug " $line ... Doesn't match"
304362 fi
@@ -526,16 +584,17 @@ function command_install() {
526584 print_debug " OK, lower case file name: $lower_file_name "
527585
528586 print_debug " Checking if file should be skipped"
529- if [[ " $lower_file_name " =~ $REGEXP_SKIP_FILES ]] ; then
587+ if regex_match " $lower_file_name " " $REGEXP_SKIP_FILES " ; then
530588 print_debug " File name matches skip pattern - Skipping: $file_name "
531589 continue
532590 fi
533591 print_debug " No skip pattern matched - File will be installed"
534592
535593 print_debug " Removing version/os/arch parts from file name if present"
536594 local regexp=$( get_name_regexp)
537- if [[ " $file_name " =~ $regexp ]]; then
538- file_name=" ${BASH_REMATCH[1]} "
595+ local match=$( regex_capture " $file_name " " $regexp " 1)
596+ if [[ -n " $match " ]]; then
597+ file_name=" $match "
539598 print_debug " OK, cleaned file name"
540599 fi
541600
@@ -620,7 +679,7 @@ function main() {
620679 throw_error 1 " Please provide either repo in format 'owner/repo_name' or known alias.\n$HELP_STRING "
621680
622681 elif [[ " $2 " == * " /" * ]]; then
623- if [[ " $2 " =~ ^[a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+$ ]] ; then
682+ if regex_match " $2 " " ^[a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+$" ; then
624683 repo=" $2 "
625684 else
626685 throw_error 2 " Given string '$2 ' is not in format 'owner/repo_name'.\n$HELP_STRING "
0 commit comments