Comment split le nom du file en variable?

Supposons que j'ai une list de files csv avec le format suivant:

INT_V1_<Product>_<ID>_<Name>_<ddmmyy>.csv ASG_B1_V1_<Product>_<ID>_<Name>_<ddmmyy>.csv 

Le INT_V1_ & ASG_B1_V1_ est corrigé, ce qui signifie que tous les files csv commencent par lui.
Comment puis-je split les noms de files en variable?
Par exemple, je voulais capturer le nom et l'atsortingbuer à une variable $Name .

Avec zsh :

 file='INT_V1_<Product>_<ID>_<Name>_<ddmmyy>.csv' setopt extendedglob if [[ $file = (#b)*_(*)_(*)_(*)_(*).csv ]]; then product=$match[1] id=$match[2] name=$match[3] date=$match[4] fi 

Avec bash 4.3 ou plus récent, ksh93t ou plus récent ou zsh en émulation sh (bien que dans zsh , vous préfèreriez simplement faire field=("${(@s:_:)field}") opérateur non-sens de sh ) vous pouvez split la string sur _ caractères et les referencer depuis la fin:

 IFS=_ set -o noglob field=($file) # split+glob operator date=${field[-1]%.*} name=${field[-2]} id=${field[-3]} product=${field[-4]} 

Ou (bash 3.2 ou plus récent):

 if [[ $file =~ .*_(.*)_(.*)_(.*)_(.*)\.csv$ ]]; then product=${BASH_REMATCH[1]} id=${BASH_REMATCH[2]} name=${BASH_REMATCH[3]} date=${BASH_REMATCH[4]} fi 

(qui suppose que le $file contient du text valide dans les parameters régionaux actuels qui n'est pas garanti pour les noms de file, sauf si vous corrigez les parameters régionaux à C ou à d'autres parameters régionaux avec un jeu de caractères d'un octet par caractère).

Comme zsh ' * ci-dessus, le .* Est gourmand . Ainsi, le premier mangera autant de *_ que possible, de sorte que le rest .* Ne fera que correspondre aux strings libres.

Avec ksh93 , vous pourriez faire

 pattern='*_(*)_(*)_(*)_(*).csv' product=${file//$pattern/\1} id=${file//$pattern/\2} name=${file//$pattern/\3} date=${file//$pattern/\4} 

Dans un script POSIX sh , vous pouvez utiliser les opérateurs d'extension de parameters standard ${var#pattern} , ${var%pattern} :

 rest=${file%.*} # remove .csv suffix date=${rest##*_} # remove everything on the left up to the rightmost _ rest=${rest%_*} # remove one _* from the right name=${rest##*_} rest=${rest%_*} id=${rest##*_} rest=${rest%_*} product=${rest##*_} 

Ou utilisez de nouveau l'opérateur split + glob:

 IFS=_ set -o noglob set -- $file shift "$(($# - 4))" product=$1 id=$2 name=$3 date=${4%.*} 

Vous pouvez prendre les valeurs de votre champ <Name> avec cette command:

 cut -d'<' -f4 < csvlist | sed -e 's/>_//g' 

(ou avec awk ):

 awk -F'<' '{print $4}' < csvlist | sed -e 's/>_//g' 

Et vous pouvez les mettre dans une variable comme ceci:

 variable_name=$(cut -d'<' -f4 < csvlist | sed -e 's/>_//g') 

ou

 awk -F'<' '{print $4}' < csvlist | sed -e 's/>_//g' 

Il n'est pas clair dans la question si vous voulez la même variable pour toutes les valeurs ou une seule variable pour chacun d'eux.

 file='INT_V1_<Product>_<ID>_<Name>_<ddmmyy>.csv' IFS=\_ read -rxx product id name date x <<< "$file" date=${date%.*}