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

时间:2017-07-11 14:23:04

标签: linux bash sed

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

可重复的示例

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

    echo -e 'Test-123\tA\tA\tC\t-\t-\tT\tG\t'
    Test-123        A       A       C       -       -       T       G
    

问题

  • 我只想用N替换 - 字符。如果该行的名称包含短划线,我需要保持这种方式。
  • 我想要的输出文件示例:

    Test-123        A       A       C       N       N       T       G
    

我尝试的解决方案

  • 我尝试使用sed

    转义
    sed -e 's,\<-\>,N,g'
    
  • 它不起作用,我检查了之前和之后的字符数,它们是相同的

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

非常感谢任何帮助。

谢谢!

7 个答案:

答案 0 :(得分:2)

另一个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        A       A       C       N       N       T       G

说明:

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        A       A       C       N       N       T       G

显然\B仅适用于GNU sed(here

另一个编辑:使用perl和lookahead。如果前者后跟\t-,我们会将\tN替换为。这样我们就可以避免重叠区域:

$ echo -e $a | perl -ne 's/\t-(?=\t)/\tN/g; print'
Test-123        A       A       C       N       N       T       G

答案 1 :(得分:1)

echo -e 'Test-123\tA\tA\tC\t-\t-\tT\tG\t'|sed 's/\B-\B/N/g'

答案 2 :(得分:1)

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

除非在方括号内使用,否则破折号不需要转义。

这只是假设只有第一列不应该替换tab-dash,并且它适用于最后一列。

答案 3 :(得分:0)

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        A       A       C       N       N       T       G

答案 4 :(得分:0)

试试这个:

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

答案 5 :(得分:0)

如果您正在寻找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    A   A   C   N   N   T   G

如果您没有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    A   A   C   N   N   T   G

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

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

答案 6 :(得分:0)

实际上,您希望将\t-\t(仅作为字段中的字符减去)的任何出现替换为\tN\n。这里的问题是2个相邻的-字段会重叠,因此sed -e 's/\t-\t/\tN\t/g是不够的。

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

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

(真实的标签已经注明了这里,但应该是文件中的真实标签)

脚本意味着:

  • :top:简单标签
  • s/\t-\t/\tN\t/:替换单个出现的&#34;标签 - 标签&#34;使用&#34;标签N标签&#34;
  • t top:如果替换发生循环,则打印替换行并迭代到下一行

你这样使用它:

$ echo -e 'Test-123\tA\tA\tC\t-\t-\tT\tG\t' | sed -f sedscript
Test-123        A       A       C       N       N       T       G

如果您不想使用外部脚本,可以使用-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        A       A       C       N       N       T       G