想要提取文件名中第 5 个 _ 之前的部分吗?

想要提取文件名中第 5 个 _ 之前的部分吗?

我有一个文件abc_asdfjhdsf_ckd_dfksfj_c_12345678_223344.txt。我想要输出为abc_asdfjhdsf_ckd_dfksfj_c.txt.

答案1

使用 sed

$ echo abc_* | sed -E 's/(([^_]*_){5}).*/\1/; s/_$/.txt/'
abc_asdfjhdsf_ckd_dfksfj_c.txt

怎么运行的:

  • s/(([^_]*_){5}).*/\1/

    这会捕获第 1 组中文件名的开头(直到第五个)_并删除其余部分。

    更详细地说,sed 的替换命令具有以下形式:s/old/new/其中old是正则表达式。在我们的例子中,正则表达式([^_]*_){5}匹配前五个部分。我们将该正则表达式放在括号中,(([^_]*_){5})以便将前五个部分保存在组 1 中,我们可以将其引用为\1.*匹配前五个组之后的所有内容。我们用前五个组替换所有这些,\1

  • s/_$/.txt/

    这会找到最后剩下的_并将其替换为.txt

使用 awk

$ echo abc_* | awk -F_ '{print $1,$2,$3,$4,$5 ".txt"}' OFS=_
abc_asdfjhdsf_ckd_dfksfj_c.txt

这用作_输入和输出字段分隔符。因此,只需打印出前五个字段,后跟.txt

替代方法:删除最后两部分

上面的代码保留前五个部分并丢弃其余部分。在问题的示例中,有七个部分,其中没有一个部分包含句点。 如果情况总是如此,那么另一种方法(帽子提示:Costas)是删除最后两部分:

$ echo abc_* | sed -E 's/(_[^_]*){2}\././'
abc_asdfjhdsf_ckd_dfksfj_c.txt

答案2

参考您想要重命名文件结尾的原始问题:

ls abc*
abc_asdfjhdsf_ckd_dfksfj_c_12345678_223344.csv

ls abc* | cut -d_ -f1-5 | awk '{print $1".txt";}'
abc_asdfjhdsf_ckd_dfksfj_c.txt

答案3

for   f in ./*_*_*_*_*_?*.txt
do    [ -e "$f" ] &&
      printf %s.txt\\n "${f%"${f#*_*_*_*_*_?}"}"
done

答案4

使用bash 参数扩展:

for f in abc_*; do f="${f%_*}"; echo "${f%_*}.txt"; done

输出:

abc_asdfjhdsf_ckd_dfksfj_c.txt

${f%_*}f是一种参数扩展模式,它将在删除最后一个_(包括)之后的所有内容后包含变量的值。

相关内容