我有一个制表符分隔的遗传变体文件,其中INFO
列有许多以分号分隔的标记:
Chr Start End Ref Alt ExAC_ALL ExAC_AFR ExAC_AMR ExAC_EAS ExAC_FIN ExAC_NFE ExAC_OTH ExAC_SAS Otherinfo QUAL DP Chr Start Ref Alt QUAL FILTER INFO
1 15847952 15847952 G C . . . . . . . . . 241.9 76196 1 15847952 . G C 241.9 PASS AC=2;AF=0;AN=18332;BaseQRankSum=0.731;ClippingRankSum=-0.731;DP=76196;ExcessHet=3.1;FS=0;InbreedingCoeff=-0.0456;MLEAC=2;MLEAF=0;MQ=38.93;MQRankSum=0.515;NEGATIVE_TRAIN_SITE;QD=10.52;ReadPosRankSum=0.89;SOR=0.481;VQSLOD=-1.406 culprit=MQ
1 15847963 15847963 A C . . . . . . . . . 1607.1 126156 1 15847963 . A C 1607.1 PASS AC=2;AF=0;AN=22004;BaseQRankSum=0.851;ClippingRankSum=-0.419;DP=126156;ExcessHet=3.4904;FS=0;InbreedingCoeff=0.0299;MLEAC=2;MLEAF=0;MQ=59.29;MQRankSum=0.18;QD=1.55;ReadPosRankSum=0.067;SOR=0.651;VQSLOD=0.995 culprit=QD
1 15847964 15847966 GCC - . . . . . . . . . 1607.1 126156 1 15847963 . AGCC A 1607.1 PASS AC=63;AF=0.003;AN=22004;BaseQRankSum=0.851;ClippingRankSum=-0.419;DP=126156;ExcessHet=3.4904;FS=0;InbreedingCoeff=0.0299;MLEAC=55;MLEAF=0.002;MQ=59.29;MQRankSum=0.18;QD=1.55;ReadPosRankSum=0.067;SOR=0.651;VQSLOD=0.995 culprit=QD
1 15847978 15847978 C T . . . . . . . . . 648.41 234344 1 15847978 . C T 648.41 PASS AC=9;AF=0;AN=25894;BaseQRankSum=-0.572;ClippingRankSum=-0.404;DP=234344;ExcessHet=3.348;FS=2.639;InbreedingCoeff=-0.0098;MLEAC=6;MLEAF=0;MQ=58.71;MQRankSum=-0.456;NEGATIVE_TRAIN_SITE;QD=4.13;ReadPosRankSum=-0.456;SOR=0.452;VQSLOD=-1.238 culprit=QD
我想在INFO列中拆分前3个以分号分隔的术语:
AC=2;AF=0;AN=18332
这样他们就变成了:
AC=2 AF=0 AN=18332 BaseQRankSum=0.731;ClippingRankSum=-0.731;DP=76196;ExcessHet=3.1;FS=0;InbreedingCoeff=-0.0456;MLEAC=2;MLEAF=0;MQ=38.93;MQRankSum=0.515;NEGATIVE_TRAIN_SITE;QD=10.52;ReadPosRankSum=0.89;SOR=0.481;VQSLOD=-1.406 culprit=M
到目前为止,我已尝试使用sed
的以下表达式:
sed -i .bk 's/\(A.=.*\);/\1 /g' allChr_ExAC38.hg38_multianno.txt
但这不会产生任何变化。
理想情况下,我一直在寻找一种方法来告诉sed
替换;
的分号tab
的前3个出现,但's/;/ /g3'
似乎没有意思是。
答案 0 :(得分:4)
使用Perl代替sed:
perl -i.bk -pe '$c = 0; s/;/\t/ while $c++ < 3' -- file.txt
答案 1 :(得分:0)
请您试着跟随并告诉我这是否对您有帮助。
awk '
FNR==1{
print;
next}
{
num=split($(NF-1),array,";");
for(i=4;i<=num;i++){
val=val?val ";"array[i]:array[i]};
$(NF-1)=array[1] OFS array[2] OFS array[3] OFS val;
val="";
$1=$1
}
1
' OFS="\t" Input_file
答案 2 :(得分:0)
你的正则表达式中的.*
是贪婪的,并且会在行上尽可能多地匹配文本,直到最后一个分号之前(但不会超出,因为那样整个正则表达式根本就不匹配)。
你不能混合/3
和/g
;后者意味着,在每一行上替换所有次出现,因此它与/3
直接相矛盾,sed
表示在一行上最多只替换三次出现。
某些正则表达式引擎支持非贪婪匹配,但.
不是其中之一。只要有一个分隔符字符就可以用来限制贪婪,无论如何使用它是一个更好的解决方案。在您的情况下,只需将[^;]
替换为sed 's/\(A.=[^;]*\);/\1 /3' allChr_ExAC38.hg38_multianno.txt
即可说出“除(换行符号)分号以外的任何字符”而不是“任何字符(换行符除外)。”
-i .bk
(这将打印到标准输出进行验证;一旦看到结果正确,就将.
放回去。)
根据您的示例数据,或许可以考虑将表达式中的剩余[A-Z]
替换为[^;]
,将[^;=]
替换为[0-9]
甚至public long SaveUsers(Users users) {
long id = -1;
ContentValues contentValues = null;
try {
contentValues = new ContentValues();
contentValues.put("name", users.getName());
contentValues.put("email", users.getEmail());
contentValues.put("phone", users.getPhone());
contentValues.put("password", users.getPassword());
db=sqliteHelper.getWritableDatabase();
id = db.insert(SqliteHelper.TABLE_USERS, null, contentValues);
} catch (Exception e) {
Log.d("Database Insert","Exception:"+e.getMessage());
} finally {
if(db!=null && db.isOpen())
db.close();
}
return id;
}
。你的正则表达式越具体越好。
答案 3 :(得分:0)
你可以试试这个awk
awk '{for(i=1;i<4;i++)sub(";","\t")}1' infile
答案 4 :(得分:0)
这可能适合你(GNU sed):
sed -i.bak 's/;/\n/3;h;y/;/\t/;G;s/\n.*\n/\t/' file
用换行符替换第三个;
,制作该行的副本,将所有;
替换为\t
,然后附上副本,使用\t
将第一行的末尾替换为第二行的中间。
根据定义,一行由换行符划分,除非由程序员引入,否则行不能包含换行符。
答案 5 :(得分:0)
如果出现次数合理,您可以多次使用管道发送 sed,即
sed -E -e 's/[0-9]{4}/****/'| sed -E -e 's/[0-9]{4}/****/'| sed -E -e 's/[0-9]{4}/****/'
将像这样屏蔽前 3 组 4 位数的信用卡号
Input:
1234 5678 9101 1234
Output:
**** **** **** 1234