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


11

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

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

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


如果在AIX 7.1上使用ksh,为什么要加上“ bash”标签?
斯特凡Chazelas

我希望产生一个bash脚本。只是我想先在ksh上尝试,抱歉给您造成麻烦。
朱丽叶。Y17年

Answers:


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

bash在sh仿真中使用4.3或更高版本,ksh93t或更高版本或zsh(尽管在中zsh,您宁愿简单地field=("${(@s:_:)field}")进行拆分,而不是使用的split + glob nonsense运算符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*上方,则.*贪婪。因此,第一个将吃掉尽可能多的东西*_,因此剩余的.*将仅匹配_-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]}
朱丽叶。Y17年

@Juliet ${field[-1]}是为bash-4.3+。对于ksh,请使用任何“ POSIX”解决方案。在ksh93t(源自zsh的功能)之前未添加对负下标的支持。
斯特凡Chazelas

好的,请注意。非常感谢,脚本工作正常。
朱丽叶。Y17年

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

请注意,这_不是特殊的,不需要引用。假定文件名不包含换行符。您可能要添加一个-d ''
斯特凡Chazelas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.