3

我正在处理一个特定的文件名,并且需要从中提取信息。

文件名的结构类似于:“20100613_M4_28007834.005_F_RANDOMSTR.raw.gz”

使用 RANDOMSTR 是一个最多 22 个字符的字符串,其中可能包含(或不包含)格式为“-W[0-9].[0-9]{2}.[0-9]{3}”的子字符串。该子字符串还具有以“-W”开头的独特功能。

我需要提取的信息是没有这个可选子字符串的 RANDOMSTR 的子字符串。

我想在 bash 脚本中实现这一点,到目前为止,我发现的最佳选择是将 gawk 与正则表达式一起使用。到目前为止,我最好的尝试失败了:

gawk --re-interval '{match ($0,"([0-9]{8})_(M[0-9])_([0-9]{8}\\.[0-9]{3})_(.)_(.*)(-W.*)?.raw.gz",arr); print arr[5]}' <<< "20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz"
OTHER-STRING-W0.40+045

预期结果是:

gawk --re-interval '{match ($0,$regexp,arr); print arr[5]}' <<< "20100613_M4_28007834.005_F_SOME-STRING.raw.gz"
SOME-STRING
gawk --re-interval '{match ($0,$regexp,arr); print arr[5]}' <<< "20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz"
OTHER-STRING

我怎样才能得到想要的效果。

谢谢。

4

4 回答 4

2

您需要能够使用环视,我不认为 awk/gawk 支持,但支持grep -P

$ pat='(?<=[0-9]{8}_M[0-9]_[0-9]{8}\.[0-9]{3}_._)(.*?)(?=(-W.*)?\.raw\.gz)'
$ echo "20100613_M4_28007834.005_F_SOME-STRING.raw.gz" | grep -Po "$pat"
SOME-STRING
$ echo "20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz" | grep -Po "$pat"
OTHER-STRING
于 2010-12-15T15:32:22.430 回答
1

虽然 grep 解决方案确实非常好,但 OP 没有提到操作系统,而且该-P选项似乎仅在 Linux 中可用。在 awk 中执行此操作也非常简单。

$ awk -F_ '{sub(/(-W[0-9].[0-9]+.[0-9]+)?\.raw\.gz$/,"",$NF); print $NF}' <<EOT
> 20100613_M4_28007834.005_F_SOME-STRING.raw.gz
> 20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz
> EOT
SOME-STRING
OTHER-STRING
$ 

请注意,这会在“20100613_M4_28007834.005_F_OTHER-STRING-W0_40+045.raw.gz”上中断。如果这是一个风险,并且-W只出现在上面显示的位置,那么使用类似的东西可能会更好:

$ awk -F_ '{sub(/(-W[0-9.+]+)?\.raw\.gz$/,"",$NF); print $NF}'
于 2012-01-31T05:45:25.857 回答
0

这里的困难似乎在于(.*)可选的前面的(-W.*)?内容吞噬了后面的文本。使用非贪婪匹配也无济于事。不幸的是,我的 regex-fu 太弱了,无法解决这个问题。

如果您不介意多通道解决方案,那么更简单的方法是首先通过删除尾随.raw.gz和可能的-W*.

str="20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz"
echo ${str%.raw.gz}  | # remove trailing .raw.gz
     sed 's/-W.*$//' | # remove trainling -W.*, if any
     sed -nr 's/[0-9]{8}_M[0-9]_[0-9]{8}\.[0-9]{3}_._(.*)/\1/p'

我使用了 sed,但你也可以使用 gawk/awk。

于 2010-12-15T15:26:25.163 回答
0

无法获得不情愿的量词,但依次运行两个正则表达式可以完成这项工作:

sed -E -e 's/^.{27}(.*).raw.gz$/\1/' << FOO | sed -E -e 's/-W[0-9.]+\+[0-9.]+$//'
20100613_M4_28007834.005_F_SOME-STRING.raw.gz
20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz
FOO
于 2012-01-31T05:25:02.550 回答