如何将文件名拆分为变量?

Jul*_*t.Y 11 bash ksh

假设我有一个具有以下格式的 csv 文件列表:

INT_V1_<Product>_<ID>_<Name>_<ddmmyy>.csv
ASG_B1_V1_<Product>_<ID>_<Name>_<ddmmyy>.csv
Run Code Online (Sandbox Code Playgroud)

INT_V1_ASG_B1_V1_是固定的,这意味着所有的CSV文件,开始使用它。
如何将文件名拆分为变量?
例如,我想捕获Name并将其分配给一个变量$Name

Sté*_*las 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
Run Code Online (Sandbox Code Playgroud)

bash在 sh 仿真中使用4.3 或更高版本、ksh93t 或更高版本或 zsh(尽管在 中zsh,您宁愿简单地field=("${(@s:_:)field}")进行拆分而不是使用 的 split+glob 无意义运算符sh),您可以将字符串拆分为_字符并从末尾引用它们:

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

或(bash 3.2 或更新版本):

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

(假设$file包含当前语言环境中的有效文本,这不能保证文件名,除非您将语言环境固定为 C 或其他每个字符字符集为单字节的语言环境)。

zsh*上方,则.*贪婪。所以第一个会吃尽可能多的*_,所以剩下的.*只会匹配_-free字符串。

有了ksh93,你可以做

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

在POSIXsh脚本,您可以使用${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##*_}
Run Code Online (Sandbox Code Playgroud)

或者再次使用 split+glob 运算符:

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


Zum*_*rio 5

您可以使用以下命令获取字段的值<Name>

cut -d'<' -f4 < csvlist | sed -e 's/>_//g'
Run Code Online (Sandbox Code Playgroud)

(或与awk):

awk -F'<' '{print $4}' < csvlist | sed -e 's/>_//g'
Run Code Online (Sandbox Code Playgroud)

你可以将它们放入一个变量中,如下所示:

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

或者

awk -F'<' '{print $4}' < csvlist | sed -e 's/>_//g'
Run Code Online (Sandbox Code Playgroud)

问题中尚不清楚您是否想要为所有值使用相同的变量,或者为每个值使用一个变量。