![想要提取文件名中第 5 个 _ 之前的部分吗?](https://linux22.com/image/75462/%E6%83%B3%E8%A6%81%E6%8F%90%E5%8F%96%E6%96%87%E4%BB%B6%E5%90%8D%E4%B8%AD%E7%AC%AC%205%20%E4%B8%AA%20_%20%E4%B9%8B%E5%89%8D%E7%9A%84%E9%83%A8%E5%88%86%E5%90%97%EF%BC%9F.png)
我有一个文件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
是一种参数扩展模式,它将在删除最后一个_
(包括)之后的所有内容后包含变量的值。