如何使用Bash删除字符串指定索引位置后所有内容
需求说明
你需要将给定氨基酸序列保留到第383次出现的Q字符位置,删除后续所有内容,现有尝试的sed命令未生效,同时需要支持后续修改不同截止位置、不同目标字符的可复用方案。
错误原因分析
你使用的sed 's/Q//383'是sed标准替换语法,作用是删除目标行中第383次出现的Q字符,和「保留到第383个Q为止所有内容」的需求完全不符,因此无法得到预期结果。
可复用实现方案
以下两种方案都支持自定义目标字符、目标出现次数,适配后续多场景处理需求:
方案1:sed实现(适合单行长序列场景)
通用命令模板,替换[目标字符]和[目标出现次数]即可直接使用:
sed -E 's/(([^[目标字符]]*[目标字符]){[目标出现次数]}).*/\1/' 输入文件
你的场景对应命令为:
sed -E 's/(([^Q]*Q){383}).*/\1/' text.file
如果需要直接修改原文件,添加-i参数即可:
sed -i -E 's/(([^Q]*Q){383}).*/\1/' text.file
正则逻辑说明:
[^Q]*Q匹配一段不含Q的字符+一个Q的组合{383}表示匹配383次上述组合,刚好覆盖到第383个Q为止的所有内容- 外层括号捕获这部分内容,后面的
.*匹配剩余所有内容,替换为捕获的内容就实现了需求
方案2:awk实现(适合多行长序列、大文件场景)
通用命令模板,修改c参数(目标字符)和k参数(目标出现次数)即可:
awk -v c="[目标字符]" -v k=[目标出现次数] 'BEGIN{FS=OFS=""}{cnt=0; for(i=1;i<=NF;i++){printf $i; if($i==c) cnt++; if(cnt==k) {print ""; next}}}' 输入文件
你的场景对应命令为:
awk -v c="Q" -v k=383 'BEGIN{FS=OFS=""}{cnt=0; for(i=1;i<=NF;i++){printf $i; if($i==c) cnt++; if(cnt==k) {print ""; next}}}' text.file
如果需要保存结果到原文件,在命令末尾添加> temp && mv temp text.file即可。
批量处理扩展
如果需要批量处理多个不同的截止位置,写shell循环传入参数即可,示例:
# 批量处理,分别保留到第100个A、200个M、383个Q for char in A M Q; do for num in 100 200 383; do sed -E "s/(([^${char}]*${char}){${num}}).*/\1/" text.file > output_${num}_${char}.fasta done done
内容的提问来源于stack exchange,提问作者tacrolimus
相关产品推荐
相关产品推荐

