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 通配符中将由 表示?
),因此如果您想匹配文字.
,则必须对其进行转义。这在替换字符串中当然不是必需的,因为那不是正则表达式。