将 sed 与模式中的变量一起使用

将 sed 与模式中的变量一起使用

I am trying to rename a couple of files with the same extensions with a differing variable in the middle. I have tried the following with no luck as to what I wish to accomplish.

文件:cKO_mESC_Rep_1_H3K27Ac.gc_corrected.bam

INBAM=$(ls *_*.gc_corrected.bam)
INPUT=$(echo $INBAM | sed 's/_*.gc_corrected.bam/_input.gc_corrected.bam/g')

echo $INPUT 
cKO_mESC_Rep_1_H3K27Ac_input.gc_corrected.bam

但是,我希望我的输出是cKO_mESC_Rep_1_input.gc_corrected.bam

有人知道错误是什么吗?我已经尝试了很多事情,但我可能无法使用正确的关键字进行搜索来获得答案。谢谢!

答案1

欢迎来到该网站。

我认为你混淆了“通配符”(又名“壳球“) 和常用表达在您使用sed.

您的意图显然是将模式“下划线,后跟任意数量的字母和数字,后跟.gc_corrected.bam”替换为_input.gc_corrected.bam。不幸的是,你的sed表达有两个方面的缺陷:

  • 您的匹配部分使用 shell 典型的“通配符”表示法。然而,这里需要sed一个正则表达式,并且在正则表达式中,*不是意思是“零个或多个字符的任何字符串”,但“前一个字符的零个或多次重复”,以便您的表达式将替换由“零个或多个下划线,后跟.gc_corrected.bam”组成的任何模式替换为_input.gc_corrected.bam。这就是为什么在您的情况下,只需将文件名后缀之前的最后一个下划线替换为_input.
  • 即便如此,如果实际文件名中有多个下划线,则匹配“由任意数量的字符组成的字符串”的模式也将包含下划线,这可能会导致匹配字符串的长度出现不良行为。特别是,正则表达式是贪婪的,如果不仔细构造,您可能最终会_mESC_Rep_1_H3K27Ac_input.

在您的情况下,正确的正则表达式是:

sed 's/_[^_]+\.gc_corrected\.bam/_input.gc_corrected.bam/g'

这将替换一个字符串,以下划线开头_,后跟一个或多个字符不是下划线的( [^_]+),后面跟着.gc_corrected.bam,替换为_input.gc_corrected.bam

另请注意在正则表达式中,.代表“任何单个字符”(在 shell 通配符中将由 表示?),因此如果您想匹配文字.,则必须对其进行转义。这在替换字符串中当然不是必需的,因为不是正则表达式。

相关内容