如何提取文件名中具有特定模式的部分?

如何提取文件名中具有特定模式的部分?

我正在寻找提取我当前正在使用的位置的文件名的一部分,但它没有按预期输出工作。

样本数据:

ls -a *0728*dat | ls -a *0728*dat |种类

amnbmnbm_jnjmnm_sd_07282019_14_13_17.dat
amnbmnb_kjhkj_07282019_11_23_22.dat
njnkjnjk_AbnBCBB_DE_07282019_07_09_04.dat

我希望从文件名中提取文件部分,从病房日期左侧的所有内容(包括下划线(_))并将其分配给 vairable

期望的输出:

变量文件是它需要保存值的东西,这样我就可以传入 for 循环

文件:

amnbmnbm_jnjmnm_sd_
amnbmnb_kjhkj_
njnkjnjk_AbnBCBB_DE_


for file_name in "${file[@]}"
do

echo " file_name=$file_name"

done

期望的输出:

amnbmnbm_jnjmnm_sd_
amnbmnb_kjhkj_
njnkjnjk_AbnBCBB_DE_

答案1

也许:

for file_name in *0728*dat
do
  printf '%s\n' "${file_name%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_[0-9][0-9]_[0-9][0-9]_[0-9][0-9].dat}"
done

这会从每个文件名的末尾删除以下模式:8 位数字,下划线,2 位数字,下划线,2 位数字,下划线,2 位数字,然后.dat.

答案2

使用 sed:

ls -a *0728*dat | sed 's/[0-9].*//'
amnbmnb_kjhkj_
amnbmnbm_jnjmnm_sd_
njnkjnjk_AbnBCBB_DE_

或者

ls -a *0728*dat | sed "s/[0-9]\{8\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}\.dat$//"

答案3

以下需要bash4.4 或更高版本、GNUfind和 GNU sed(或者至少支持 NUL 作为输出/输入分隔符的afind和 a ):sed

$ mapfile -d '' files < <(find . -maxdepth 1 -type f -iname '*0728*.dat' -print0 | 
    sed -z 's:^\./::; s/[0-9][0-9_]\+.dat//')

在删除前导、日期和时间以及 .dat 扩展名files后,这将使用当前目录中的匹配文件名填充 bash 数组 ( ) 。它使用 NUL 作为记录(即文件名)分隔符,以避免任何文件名中存在空格、换行符、shell 元字符等的任何潜在问题。./sed

find使用 是因为您永远不应该使用 的输出ls作为其他程序的输入或作为另一个程序命令行上的参数 - 这是不安全且不可靠的。看为什么不是解析ls(以及该怎么做)?

当然,可以修改该find命令以查找匹配不同模式的文件,或者在子目录等中。

例子:

$ touch amnbmnbm_jnjmnm_sd_07282019_14_13_17.dat amnbmnb_kjhkj_07282019_11_23_22.dat \
    njnkjnjk_AbnBCBB_DE_07282019_07_09_04.dat

$ mapfile -d '' files < <(find . -maxdepth 1 -type f -iname '*0728*.dat' -print0 | 
    sed -z 's:^\./::; s/[0-9][0-9_]\+.dat//')

$ typeset -p files
declare -a files=([0]="amnbmnbm_jnjmnm_sd_" [1]="amnbmnb_kjhkj_" [2]="njnkjnjk_AbnBCBB_DE_")

$ printf '%s\n' "${files[@]}"
amnbmnbm_jnjmnm_sd_
amnbmnb_kjhkj_
njnkjnjk_AbnBCBB_DE_

相关内容