fName1=$(echo $fileName | awk -F"-" '{ print $3 }')

CUT the file name from $3 to until date value

I need file name to be like this :


To extract part of strings following a pattern, you can use expr:

expr " $fileName" : '[^-]*-[^-]*-\(.*_[0-9]\{4\}-[01][0-9]-[0-3][0-9]\)_'

(here extracting the part after the second - and up to the rightmost occurrence of _YYYY-MM-DD_ (trailing _ not included))

Or with zsh:

set -o extendedglob
[[ $fileName = (#b)[^-]#-[^-]#-(*_[0-9](#c4)-[01][0-9]-[0-3][0-9])_* ]] &&
  print -r - $match[1]


set -o rematchpcre
[[ $fileName =~ '^.*?-.*?-(.*_\d{4}-[01]\d-[0-3]\d)_' ]] &&
  print -r - $match[1]

Or with ksh93:

printf '%s\n' "${fileName/#*([^-])-*([^-])-@(*_{4}(\d)-[01][0-9]-[0-3][0-9])_*/\3}"

Or with bash:

[[ $fileName =~ ^[^-]*-[^-]*-(.*_[0-9]{4}-[01][0-9]-[0-3][0-9])_ ]] &&
  printf '%s\n' "${BASH_REMATCH[1]}"

You seem to want to delete the two first and last three strings delimited by a dash (-) from the value $fileName. This is most efficiently done with a parameter substitution ("efficient" = does not use any external program, just the shell).

$ fileName=20201211-v1-ABC144_newrecords_2020-12-10_12-51-32-000_2444_511
$ fileName=${fileName#*-*-}
$ echo "$fileName"
$ fileName=${fileName%-*-*-*}
$ echo "$fileName"

The substitution ${fileName#*-*-} will be the value $fileName but with the bit that matches the pattern *-*- at the start removed. In a similar manner, ${fileName%-*-*-*} will be $fileName but with the bit that matches -*-*-* at the end removed.


The easiest way to do this is probably using cut:

printf '%s\n' "$fileName" | cut -d- -f3-5

This just sets the delimiter to “-“ and extracts fields 3-5.

It assumes the file name doesn't contain whitespace characters.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.