Удалить символ из середины строки - PullRequest
2 голосов
/ 01 мая 2019

У меня есть файл SAM с полем RX:, содержащим 12 баз, разделенных посередине -, т.е. RX:Z:CTGTGC-TCGTAA

Я хочу удалить дефис из этого поля, но я не могу просто удалить все дефисы из всего файла, так как имена для чтения содержат их, например 1713704_EP0004-T

В основном пытались tr,, но это просто удаление всех дефисов из файла .:

tr -d '"-' < sample.fq.unaln.umi.sam > sample.fq.unaln.umi.re.sam

input - это большой файл SAM, содержащий> 10 000 000 строк, например:

1902336-103-016_C1D1_1E-T:34    99  chr1    131341  36  146M    =   131376  182 GGACAGGGAGTGTTGACCCTGGGCGGCCCCCTGGAGCCACCTGCCCTGAAAGCCCAGGGCCCGCAACCCCACACACTTTGGGGCTGGTGGAACCTGGTAAAAGCTCACCTCCCACCATGGAGGAGGAGCCCTGGGCCCCTCAGGGG  NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN  MC:Z:147M   MD:Z:83T62cD:i:4    cE:f:0  PG:Z:bwa    RG:Z:A  MI:Z:34 NM:i:1  cM:i:3  MQ:i:36 UQ:i:45 AS:i:141    XS:i:136    RX:Z:CTGTGC-TCGTAA

Желаемый вывод (т. Е. Последнее поле)

1902336-103-016_C1D1_1E-T:34    99  chr1    131341  36  146M    =   131376  182 GGACAGGGAGTGTTGACCCTGGGCGGCCCCCTGGAGCCACCTGCCCTGAAAGCCCAGGGCCCGCAACCCCACACACTTTGGGGCTGGTGGAACCTGGTAAAAGCTCACCTCCCACCATGGAGGAGGAGCCCTGGGCCCCTCAGGGG  NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN  MC:Z:147M   MD:Z:83T62cD:i:4    cE:f:0  PG:Z:bwa    RG:Z:A  MI:Z:34 NM:i:1  cM:i:3  MQ:i:36 UQ:i:45 AS:i:141    XS:i:136    RX:Z:CTGTGCTCGTAA

Как мне решить эту проблему?

Ответы [ 4 ]

5 голосов
/ 01 мая 2019

awk

awk '{sub(/-/,"",$NF)}1' file

- это то, что вам нужно.

Пояснение

  • От это ясно, что вас беспокоит только последнее поле.
  • NF - это общее количество полей, содержащихся в записи, следовательно, $ NF - последнее поле.
  • sub(/-/,"",$NF) заменяет - в последнем поле пустой строкой, делая изменение постоянным.

GNU sed

Для this та же причина,

sed -Ei 's/^(.*)-/\1/' file

будет работать.У него есть дополнительное преимущество, заключающееся в том, что он может выполнять редактирование на месте.

Пояснение

  • Опция -E включает расширенный механизм регулярных выражений.
  • (.*) - это жадный поиск, который будет соответствовать любому символу (.) любое количество раз (*).Для того факта, что он жадный, он будет соответствовать чему угодно до последнего дефиса.
  • * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  • .совпавшая часть \1 (1, потому что у нас только одна пара скобок, обратите внимание, что вы можете иметь столько, сколько вам нужно) без дефиса, таким образом, эффективно удаляя его из последнего поля, где он должен находиться.

Примечание: GNU awk поддерживает -i inplace, но я не уверен, какая версия включена.

2 голосов
/ 10 мая 2019

Я решил эту проблему с помощью pysam, который работает быстрее, безопаснее и требует меньше места на диске, поскольку файл sam не требуется.Это не идеально, я все еще изучаю Python и использую pysam в течение половины дня.

import pysam
import sys
from re import sub

# Provide a bam file
if len(sys.argv) == 2:
    assert sys.argv[1].endswith('.bam')

# Makes output filehandle
inbamfn = sys.argv[1]
outbamfn = sub('.bam$', '.fixRX.bam', inbamfn)

inbam = pysam.Samfile(inbamfn, 'rb')
outbam = pysam.Samfile(outbamfn, 'wb', template=inbam)

# Counters for reads processed and written
n = 0
w = 0

# .get_tag() retrieves RX tag from each read
for read in inbam.fetch(until_eof=True):
    n += 1
    umi = read.get_tag('RX')
    assert umi is not None
    umifix = umi[:6] + umi[7:]
    read.set_tag('RX', umifix, value_type='Z')
    if '-' in umifix:
        print('Hyphen found in UMI:', umifix, read)
        break
    else:
        w += 1
        outbam.write(read)

inbam.close()
outbam.close()

print ('Processed', n, 'reads:\n',
       w, 'UMIs written.\n',
       str(int((w / n) * 100)) + '% of UMIs fixed')

1 голос
/ 09 мая 2019

Лучшее решение - работать с файлами BAM, а не с файлами SAM, и использовать правильную библиотеку BAM-анализатора / записи, такую ​​как htslib.

Не имея этого, вы можете что-то объединить, выполняя поиск обычноговыражение ^RX:Z: в необязательных тегах (столбцы 12 и выше).

Работа с столбцами, хотя и возможна, затруднена с помощью sed.Вместо этого, вот как это сделать в awk:

awk -F '[[:space:]]*' '{
    for (i = 12; i <= NF; i++) {
        if ($i ~ /^RX:Z:/) gsub("-", "", $i)
    }
}
1' file.sam

И вот примерно такое же решение в виде Perl «однострочный»:

perl -ape '
    for (@F[11..(scalar @F)]) {
        s/-//g if /^RX:Z:/;
    }
    $_ = join("\t", @F);
' file.sam

Чтобы выполнить замену в оригиналефайл, вы можете передать параметр -i.bak в perl (это создаст резервную копию file.sam.bak; если вы не хотите резервное копирование, опустите расширение).

0 голосов
/ 01 мая 2019

Этот шаблон на многих записях, которые вы хотите редактировать, и всегда в конце строки?Если так -

sed -E 's/^(.*)(\s..:.:......)-(......\s*)$/\1\2\3/' < sample.fq.unaln.umi.sam > sample.fq.unaln.umi.re.sam
...