ファイル名を変数に分割する方法は?


11

次の形式のcsvファイルのリストがあるとします。

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

INT_V1_ASG_B1_V1_はすべてCSVファイルには、それに開始を意味し、固定されています。
ファイル名を変数に分割するにはどうすればよいですか?
たとえば、名前を取得して変数に割り当てたいと考えました$Name


AIX 7.1でkshを使用しているのに、なぜ「bash」タグなのですか?
ステファンChazelas

bashスクリプトを作成したいと思います。最初にkshで試してみたかっただけです。
Juliet.Y 2017年

回答:


7

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

bashSHエミュレーション中4.3以降、ksh93t以降またはzshの(中けれどもzsh、あなたではなく、単純にやるだろうとfield=("${(@s:_:)field}")のスプリット+グロブ非センス演算子を使用するよりも、分割のためにsh)あなたは上の文字列を分割でき_、文字と終了からそれらを参照:

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

または(bash 3.2以降):

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

$file現在のロケールで有効なテキストが含まれていることを前提としていますが、ロケールをCまたは文字ごとに1バイト文字セットのその他のロケールに修正しない限り、ファイル名は保証されません)。

同様zsh*上記の、.*ある貪欲。したがって、最初のものは*_できるだけ多くを食べるので、残り.*_-free文字列とのみ一致します。

ksh93、あなたはできる

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

POSIX shスクリプトでは${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##*_}

または、split + glob演算子をもう一度使用します。

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

AIX7.1でbashを使用していて、現在kshでテストしています。どういうわけか私はというエラー発生したksh: file: 0403-046 The specified subscript cannot be greater than 4095.ため${field[-1]}か、フォームには何も${x[n]}
Juliet.Y 2017年

@ジュリエット、の${field[-1]}ためだったbash-4.3+。についてkshは、「POSIX」ソリューションのいずれかを使用します。負の添え字のサポートは、ksh93t(zshに由来する機能)の前に追加されませんでした。
ステファンChazelas

書き留めました。おかげで、スクリプトは正常に動作しています。
Juliet.Y 2017年

4

<Name>次のコマンドでフィールドの値を取得できます。

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

(またはawk):

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

そして、これらを次のように変数に入れることができます:

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

または

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

すべての値に同じ変数が必要か、値ごとに1つの変数が必要かは、質問では明確ではありません。


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

これ_は特別なものではなく、引用する必要がないことに注意してください。これは、ファイル名に改行文字が含まれていないことを前提としています。を追加することができます-d ''
ステファンChazelas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.