在制表符分隔的文本文件中replace单个字符,短划线

我正在运行GNU bash,版本4.3.46(2)-release(x86_64-pc-msys)

可重复的例子

  • 我有一个大的制表符分隔的文本文件,有许多行和列。 这只是数据格式的一个例子

    echo -e 'Test-123\tA\tA\tC\t-\t-\tT\tG\t' Test-123 AAC - - TG 

问题

  • 我只想用Nreplace – 字符。如果行的名字包含短划线,我需要保持这种方式。
  • 我想要的输出文件的例子:

     Test-123 AACNNTG 

我试过的解决scheme

  • 我试着逃避 – 使用sed

     sed -e 's,\<-\>,N,g' 
  • 它没有工作,我检查前后的字符数,他们是一样的

     tr -cd - < test2_chr01.txt | wc -c 

任何帮助将非常感激。

谢谢!

sed -e 's/\t-/\tN/g'

据我所知,短划线除非在方括号内使用,否则不需要转义。

这只是假设只有第一列不应该有tab-dash被替换,并且它对最后一列工作得很好。

另一个awk:

 $ a='Test-123\tA\tA\tC\t-\t-\tT\tG\t' $ echo -e $a | awk 'BEGIN{FS=OFS="\t"}{for(i=1;i<=NF;i++)if($i=="-")$i="N"}1' Test-123 AACNNTG 

解释:

 awk ' BEGIN { FS=OFS="\t" } # delimiters { for(i=1;i<=NF;i++) # for each field if($i=="-") # if a single dash $i="N" # overwrite it }1' # output 

编辑 :如果你正在寻找一个sed解决方案:

 $ echo -e $a | sed -e 's/\B-\B/N/g' Test-123 AACNNTG 

显然\B只在GNU sed上工作( 这里 )

另一个编辑 :使用perl和lookahead。 我们用\tN替换\t- ,前者后面是 。 这样我们可以避免重叠区域:

 $ echo -e $a | perl -ne 's/\t-(?=\t)/\tN/g; print' Test-123 AACNNTG 
 echo -e 'Test-123\tA\tA\tC\t-\t-\tT\tG\t'|sed 's/\B-\B/N/g' 

awk解决方案:

 echo -e 'Test-123\tA\tA\tC\t-\t-\tT\tG\t' | awk -v OFS='\t' '{ for(i=2;i<=NF;i++) sub("-","N",$i) }1' 

输出:

 Test-123 AACNNTG 

如果你正在寻找一个sed解决方案,那么下面应该与gnu sed工作:

 echo -e 'Test-123\tA\tA\tC\t-\t-\tT\tG\t' | sed ':a;s/\t-\t/\tN\t/g;ta;' Test-123 AACNNTG 

如果你没有gnu sed然后使用:

 echo -e 'Test-123\tA\tA\tC\t-\t-\tT\tG\t' | sed -e ':a' -e $'s/\\\t-\\\t/\\\tN\\\t/g;ta' Test-123 AACNNTG 

如果你有perl命令行,那么使用这个基于正则表达式的查找:

 echo -e 'Test-123\tA\tA\tC\t-\t-\tT\tG\t' | perl -pe 's/(?<=\s)-(?=\s)/N/g' Test-123 AACNNTG 

事实上,你想用\tN\n替换\t-\t (只减去字段中的字符)。 这里的问题是两个相邻的字段会重叠,所以sed -e 's/\t-\t/\tN\t/g是不够的。

你必须使用一个真正的脚本说它是文件sedscript:

 :top s/\t-\t/\tN\t/ t top 

(真正的标签已经注意到\ t在这里,但应该是真正的标签在文件中)

脚本意思是:

  • :top :简单的标签
  • s/\t-\t/\tN\t/ :将“tab – tab”中的一个出现替换为“tab N tab”
  • t top :如果替换发生循环,否则打印替换的行并迭代到下一个

你这样使用它:

 $ echo -e 'Test-123\tA\tA\tC\t-\t-\tT\tG\t' | sed -f sedscript Test-123 AACNNTG 

如果您不想使用外部脚本,则可以使用-e一次传递一个命令:

 $ echo -e 'Test-123\tA\tA\tC\t-\t-\tT\tG\t' | sed -e ':a' -e $'s/\\\t-\\\t/\\\tN\\\t/g' -e 'ta' Test-123 AACNNTG 

尝试这个:

echo -e 'Test-123\tA\tA\tC\t-\t-\tT\tG\t' | sed -e 's/\([[:space:]]\)-\{1,\}/\1N/g'