Bash:按模式提取文件名并将其插入数组
我有一个文件夹中的文件列表,我想用以下模式提取文件名并将它们插入数组 这种模式是,文件名总是以“MCABC_u”或“MCBBC_u”开头,然后是日期,然后以“.csv”结尾 例如,“MCABC_20110101.csv”、“MCBBC_20110304.csv” 现在,我只能提出下面的解决方案,但它并不理想Bash:按模式提取文件名并将其插入数组,bash,Bash,我有一个文件夹中的文件列表,我想用以下模式提取文件名并将它们插入数组 这种模式是,文件名总是以“MCABC_u”或“MCBBC_u”开头,然后是日期,然后以“.csv”结尾 例如,“MCABC_20110101.csv”、“MCBBC_20110304.csv” 现在,我只能提出下面的解决方案,但它并不理想 ls | grep-E“MCABC_U8;[A-Za-z0-9]*| MC221_U8;[A-Za-z0-9]*” 我读到使用ls是不好的。我应该使用glob 我对bash脚本完全不熟悉。如
ls | grep-E“MCABC_U8;[A-Za-z0-9]*| MC221_U8;[A-Za-z0-9]*”
我读到使用ls
是不好的。我应该使用glob
我对bash脚本完全不熟悉。如何用上面的模式提取文件名并将其插入数组中?谢谢
更新:感谢您的回答。非常感谢您的回答。我有以下代码
#!/bin/bash
shopt -s nullglob
files=(MC[1-2]21_All_[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].csv)
echo ${#files[*]}
echo ${files[0]}
这是我运行bash testing.sh
时得到的结果
:无效的shell选项名称:第2行:shopt:nullglob
1.
(MC[1-2]21.[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].csv)
但是,如果我只是在命令行files=(MC[1-2]21_All[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].csv)
上运行,然后echo${files[*]}
,我会设法获得输出:
MC121_All_20180301.csv MC121_All_20180302.csv MC121_All_20180305.csv MC221_All_20180301.csv MC221_All_20180302.csv MC221_All_20180305.csv
我很困惑。为什么会发生这种情况?(请注意,我是在10号窗口的ubuntu上运行的。)我想你可以直接用glob填充数组:
files=( MC[AB]BC_[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].csv )
“日期”部分当然可以改进,因为它匹配完全无效的日期,如98765432,但这可能不是问题。这将在BASH中起作用
#!/bin/bash
for file_name in M*
do
line="$line $( printf "${file_name%_*}")"
done
array=( $line )
echo "${array[2]}"
另一种方式:
问候!考虑使用来进行文件搜索。是的。我确实尝试过使用find,即
find.-regextype sed-regex'MC121'
但它不返回任何内容。我对bash和regex非常陌生。我不太确定哪里出错了。我认为OP需要真实的文件名,而不是虚构的。对不起,我不明白你的意思。如果我的目录中有MCABC_20110101.csv
和MCBBC_20110304.csv
,这将创建一个包含这两个文件名的数组。我刚刚在命令行上测试了您的代码行,它成功了。但当我将同一行代码放在shell脚本中时,它失败了,echo${files[*]}
返回1,而echo${files[0]}
返回(MC[AB]BC_uu0;[0-9][0-9][0-9][0-9][0-9][0-9].csv)
。我做错了什么?那是因为glob无法匹配任何文件,所以数组中只有一个元素:glob本身。您可以使用shell选项shopt-s nullglob来防止这种情况发生(这将导致空数组)或shopt-s failglob
(这将导致错误消息)但是我在命令行上测试了同一行代码,它成功地输出了我想要的文件名。只是当我将它放入bash脚本时,它失败了。我还添加了您提到的选项,它返回了:无效的shell选项名称g:line 4:shopt:nullglob
我不明白您为什么要使用printf
,但在变量之前应该始终使用格式说明符,例如%s
。我不知道为什么要删除文件名中最后一个
之后的所有内容,我建议不要使用依赖于单词拆分的做法,如数组=($line)
。请注意,如果要在循环中构建数组,可以使用files\u array+=(“$file\u name”)
。
#!/bin/bash
declare -a files_array
i=0
for file_name in M*
do
files_array[$i]="$( printf "${file_name%_*}")"
(( i++ ))
done
echo "${files_array[2]}"