假设我有一个具有以下格式的 csv 文件列表:
INT_V1_<Product>_<ID>_<Name>_<ddmmyy>.csv
ASG_B1_V1_<Product>_<ID>_<Name>_<ddmmyy>.csv
这INT_V1_&ASG_B1_V1_是固定的,这意味着所有 csv 文件都以它开头。
如何将文件名拆分为变量?
例如,我想捕捉姓名& 将其分配给一个变量$Name
。
答案1
和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
使用bash
4.3 或更新版本、ksh93t 或更新版本或 sh 模拟中的 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]}
或者(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 或其他具有单字节每个字符字符集的语言环境)。
就像上面zsh
的一样*
,.*
是贪婪的。所以第一个会吃掉尽可能多的东西*_
,所以剩下的.*
只会匹配_
无匹配的字符串。
有了ksh93
,你可以做
pattern='*_(*)_(*)_(*)_(*).csv'
product=${file//$pattern/\1}
id=${file//$pattern/\2}
name=${file//$pattern/\3}
date=${file//$pattern/\4}
在 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##*_}
或者再次使用 split+glob 运算符:
IFS=_
set -o noglob
set -- $file
shift "$(($# - 4))"
product=$1 id=$2 name=$3 date=${4%.*}
答案2
<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'
问题中尚不清楚您是否想要为所有值使用相同的变量,或者为每个值使用一个变量。
答案3
file='INT_V1_<Product>_<ID>_<Name>_<ddmmyy>.csv'
IFS=\_ read -r x x product id name date x <<< "$file"
date=${date%.*}
答案4
像这样
$ basename file.csv .csv
file