扫描和抓取

扫描和抓取

我有一个文件 ( *.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命令的作用可以描述如下

  1. -n除非匹配,否则不打印任何内容
  2. /rea ses/只考虑与此 RE 匹配的行
  3. s!...!...!p将前两个感叹号 ( !) 中的 RE 替换为后面的字符串,但仅在出现匹配时才打印该行
  4. RE^.*/\(.*\)\.[^.]*$匹配

    • 直到最后一个斜杠的所有内容/
    • 从那里到最后一个点的所有内容.(记住为模式\1
    • 其他一切
  5. #4 中描述的模式的替换是用 pattern 进行的\1,即您的文件名不带尾随点扩展名

答案4

您可以使用basename删除尾随扩展名:

cat a4.ses | grep -im1 'rea ses' | awk -F'[/]' '{print $NF}' | xargs basename -s .ses\' 

(为了完整性而提交,考虑到您的流程,@steeldriver 的答案更好)

相关内容