我有一个文件 ( *.ses
),其中包含以下行
$ rea ses '../../../../abcdefgh/abcd_efgh-A20_ABC-abcdefgh-Abcdefgh_Abcdef_123er_vb001.ses'
当我使用这个命令时:
cat a4.ses | grep -im1 'rea ses' | awk -F'[/]' '{print $NF}'
输出是:
abcd_efgh-A20_ABC-abcdefgh-Abcdefgh_Abcdef_123er_vb001.ses'
我只想输出为:
abcd_efgh-A20_ABC-abcdefgh-Abcdefgh_Abcdef_123er_vb001
没有扩展名。
我怎样才能做到这一点?
答案1
如果.ses'
是静态扩展,只需将删除尾随 5 个字符的操作硬编码到 awk 中,方法是从开头打印字符串到末尾 5 个字符:
awk -F/ '{print substr($NF, 1, length($NF)-5)}'
如果扩展名的长度可能不同,则在打印之前将其替换为空字符串:
awk -F/ '{gsub(/\..+$/, "", $NF); print $NF}'
答案2
如果您grep
支持 perl 兼容的正则表达式 (PCRE) 语法:
$ grep -Po 'rea ses.*/\K[^.]*' file
abcd_efgh-A20_ABC-abcdefgh-Abcdefgh_Abcdef_123er_vb001
解释:
- 匹配
rea ses
然后贪婪地一切直到/
包容;然后 - 匹配最长的非句点字符序列
- 丢弃 (
\K
) 左侧部分并仅输出匹配 (-o
)的剩余部分
答案3
您可以放弃该管道并sed
使用
sed -n '/rea ses/s!^.*/\(.*\)\.[^.]*$!\1!p' a4.ses
输出
abcd_efgh-A20_ABC-abcdefgh-Abcdefgh_Abcdef_123er_vb001
该sed
命令的作用可以描述如下
-n
除非匹配,否则不打印任何内容/rea ses/
只考虑与此 RE 匹配的行s!...!...!p
将前两个感叹号 (!
) 中的 RE 替换为后面的字符串,但仅在出现匹配时才打印该行RE
^.*/\(.*\)\.[^.]*$
匹配- 直到最后一个斜杠的所有内容
/
- 从那里到最后一个点的所有内容
.
(记住为模式\1
) - 其他一切
- 直到最后一个斜杠的所有内容
#4 中描述的模式的替换是用 pattern 进行的
\1
,即您的文件名不带尾随点扩展名
答案4
您可以使用basename
删除尾随扩展名:
cat a4.ses | grep -im1 'rea ses' | awk -F'[/]' '{print $NF}' | xargs basename -s .ses\'
(为了完整性而提交,考虑到您的流程,@steeldriver 的答案更好)