Extracting part of path containing a number in bash

Could you please try following, written and tested with shown samples. This should print if we have more than 1 values in the lines too. If you talk about better way, awk could be fast compare to pure bash loop + regex solutions IMHO, so adding it here.

awk -F'/' '
{
  val=""
  for(i=1;i<=NF;i++){
    if($i~/[0-9][a-zA-Z]/ || $i~/[a-zA-Z][0-9]/){
      val=(val?val OFS:"")$i
    }
  }
  print val
}' Input_file

Explanation: Adding detailed explanation for above.

awk -F'/' '                                              ##Starting awk program from here and setting field separator as / here.
{
  val=""                                                 ##Nullifying val here.
  for(i=1;i<=NF;i++){                                    ##Running for loop till value of NF.
    if($i~/[0-9][a-zA-Z]/ || $i~/[a-zA-Z][0-9]/){        ##Checking condition if field value is matching regex of digit alphabet then do following.
      val=(val?val OFS:"")$i                             ##Creating variable val where keep on adding current field value in it.
    }
  }
  print val                                              ##Printing val here.
}' Input_file                                            ##Mentioning Input_file name here.

  1. Replace / by a newline
  2. Filter the first match with a number

mypath='my/path/to/version/5e/is/7/here'
<<<"${mypath//\//$'\n'}" grep -m1 '[0-9]'

and a safer alternative that uses zero separated stream with GNU tools in case there are newlines in the path:

<<<"${mypath}" tr '/' '\0' | grep -z -m1 '[0-9]'

Is there a better way than looping over the parts using while and checking each part for a number?

No, either way or another you have to loop through all the parts until the first part with numbers is discovered. The loop may be hidden behind other tools, but it's still going to loop through the parts. You solution seems to be pretty good by itself, just break after you've found the first part if you want only the first.


Using Bash's regex:

[[ "$mypath" =~ [^/]*[0-9]+[^/]* ]] && echo "${BASH_REMATCH[0]}" 
5e

Method using 'grep -o'.

echo $mypath | grep -o -E '\b[^/]*[0-9][^/]*\b' | head -1

Tags:

Regex

Bash

Awk