每次替换时评估sed中的表达

时间:2018-10-29 13:54:59

标签: awk sed

我想用“ A”或“ T”替换一行文本中的特定字符“ M”。对于文本行中的每个“ 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

我将得到所有“ A”

AAAA

或所有“ T”

TTTT

是否可以通过sed进行这项工作?还是用awk做到这一点的等效方法?感谢您的帮助!

3 个答案:

答案 0 :(得分:0)

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' 

请注意,随机化将不会完全统一,尤其是对于低计数而言。如果您需要在所有字符中进行相同数量的替换,则应非随机地进行。

答案 1 :(得分:0)

这可能对您有用(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

如果要替换的字符不在当前行中,请跳过此行。否则,复制当前行并将其转换为随机的AT的字符串。将此字符串追加到当前行,并用字符串的开头替换每个M,直到满足所有M为止。然后打印当前行并删除图案空间中剩余的所有内容。

答案 2 :(得分:0)

只要是单个字符,就可以将tr与非常长的随机目标字符串一起使用。

tr M AAATTATAAATTTTATTTAAAT... <inputfile

tr将根据需要绕圈多次;因此在此示例中,前三个M:s将由A替换,随后的两个M将由T替换,依此类推,直到目标映射字符串用尽时重新开始。如果您想避免任何循环,那就把它真的真的很长。

tr M $(dd if=/dev/urandom bs=65536 count=1 | tr `\000-\077' A | tr -c A T) <inputfile