оценивать выражение в sed с каждой заменой - PullRequest
0 голосов
/ 29 октября 2018

Я хочу заменить определенный символ «M» в строке текста на «A» или «T». Выбор замены на «А» или «Т» должен происходить случайным образом для каждого «М» в строке текста.

Я пытался написать скрипт, используя sed для этого, но оценка случайного выбора «A» или «T» происходит только один раз на всей строке, а не при каждой замене. Мой скрипт выглядит так:

#!/bin/bash

ambM[0]=A
ambM[1]=T

file_in=${1?Error: no input file}

cat $file_in | sed "s/M/${ambM[$[$RANDOM % 2]]}/g"

Но если я использую это с файлом, который состоит из одной строки "M":

MMMM

Я получу либо все "А"

AAAA

Или все "Т"

TTTT

Есть ли что-нибудь, что можно сделать, чтобы заставить эту работу работать с sed? Или, может быть, эквивалентный способ сделать это с помощью awk? Спасибо за любую помощь!

Ответы [ 3 ]

0 голосов
/ 30 октября 2018

Это может работать для вас (GNU sed & shuf):

sed '/M/!b;h;x;s/./A\nT\n/g;s/.*/echo "&"|shuf/e;s/\n//g;x;G;:a;s/M\(.*\n\)\(.\)/\2\1/;ta;P;d' file

Если нужного символа для замены нет в текущей строке, пропустите эту строку. В противном случае скопируйте текущую строку и преобразуйте ее в строку случайных A и T. Добавьте эту строку к текущей строке и заменяйте каждый M заголовком строки, пока не будут обработаны все M. Затем напечатайте текущую строку и удалите все, что осталось в пространстве шаблона.

0 голосов
/ 30 октября 2018

Пока это одиночные символы, вы можете использовать tr с очень длинной рандомизированной целевой строкой.

tr M AAATTATAAATTTTATTTAAAT... <inputfile

tr будет кружить столько раз, сколько необходимо; поэтому в этом примере первые три M: s будут заменены на A, затем следующие два на T и т. д., начиная с того момента, когда строка назначения будет исчерпана. Просто сделайте это действительно очень долго, если вы хотите избежать каких-либо циклов.

tr M $(dd if=/dev/urandom bs=65536 count=1 | tr `\000-\077' A | tr -c A T) <inputfile
0 голосов
/ 29 октября 2018

awk на помощь!

$ echo MMMMMMMMM | awk 'BEGIN {srand()} 
                              {do x=(rand()<0.5?"A":"T"); 
                               while (sub("M",x))}1' 

TTTAATTTT

в более общем смысле, для любого числа заменяющих символов, указанных в переменной r

$ ... | awk -v r='A T C G' 'BEGIN{n=split(r,c); srand()} 
                                 {do x=c[int(rand()*n)+1];
                                  while (sub("M",x))}1' 

обратите внимание, что рандомизация не будет полностью равномерной, особенно для низких показателей. Если вам нужно одинаковое количество замен во всех символах, это должно быть сделано неслучайно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...