如何用逗号替换特定模式后的空格?
How to replace spaces after a certain pattern with commas?
我是编码新手,正在尝试格式化一些生物信息学数据。我试图用逗号删除 GT:GL:GOF:GQ:NR:NV
之后的所有空格,但不删除格式 xx:xx:xx:xx:xx
之外的任何内容(如示例)。我知道我需要使用 sed
和正则表达式选项,但我不太熟悉如何使用它。我以前从未真正使用过 sed
并且在尝试时感到困惑,因此我们将不胜感激。对不起,如果我的格式不好(这是我的第一个 post)。
编辑 2:这次我从文件中获得了实际数据,这可能有助于解决问题。删除了错误的例子。
新示例:我从我的实际文件中提取此数据(这只是两个示例),它被其他数据包围。本质上,该行有一堆数据,后跟 "GT:GL:GOF:GQ:NR:NV ",之后有更多格式如下所示的数据,最后还有一些随机数据。不幸的是,我无法 post 整行数据,因为它太长了,放不下。
输入
0/1:-1,-1,-1:146:28:14,14:4,0 0/1:-1,-1,-1:134:6:2,2:1,0
输出
0/1:-1,-1,-1:146:28:14,14:4,0,0/1:-1,-1,-1:134:6:2,2:1,0
我假设 xx:xx:xx
或 xx:xx:xx:xx
可以有任意数量的部分,因为有些有 3 个,有些有 4 个。
这很难用 sed
可靠地完成,因为它不支持环顾四周,这似乎是本例中可能需要的。
您可以尝试类似的方法:
perl -pe 's/(?<=\d) (?=\d+(:\d+){2,})/,/g' input.txt
如果你对 sed
有信心,你可以试试这个,但它可能会漏掉一些情况:
sed -r 's/(:[0-9]+) ([0-9]+:)/,/g' input.txt
您也可以在没有正则表达式的情况下使用 awk 实现您想要的结果:
awk '{printf "%s", FSFSFSFS","","; for (i=8;i<=NF;i++) printf "%s", FS$i; print ""}' input.txt
基本上,它从字段 1 到 5 使用默认字段分隔符 ("space") 输出,然后从字段 5 到 7 使用逗号分隔符,然后从字段 8 开始再次使用默认分隔符。
使用基本正则表达式,您可以使用字符类和反向引用来完成您的任务,例如
$ sed 's/\([0-9][0-9]*:[0-9][0-9]*\)[ ]\([0-9][0-9]*:[0-9][0-9]*\)/,/g' file
1/0 ./. 0/1 GT:GL:GOF:GQ:NR:NV 1:12:314,213:132:13:31,14:31:31 AB GT BB
1/0 ./. 0/1 GT:GL:GOF:GQ:NR:NV 10:13:12,41:41:1:13,13:131:1:1 AB GT RT
1/0 ./. 0/1 GT:GL:GOF:GQ:NR:NV 1:12:314,213:132:13:31,14:31:31 AB GT
基本上说:
- 查找并捕获任何
[0-9][0-9]*
一位或多位数字,
- 由
:
和 分隔
- 后跟
[0-9][0-9]*
一个或多个数字 -- 作为捕获组 1,
- 匹配捕获组 1 之后的 space 和捕获组 2(与捕获组 1 相同),
- 然后用逗号替换捕获组分隔符 space 使用反向引用 1 和 2(例如
</code> 和 <code>
)重新插入捕获组文本,最后
- 进行替换全局(例如
g
)以替换所有匹配项。
根据发布的新输入进行编辑
如果您仍然需要添加所有原始逗号, 和 您现在想要在 ,0 0/
之间添加一个逗号(逗号在单个 -数字后跟 space 替换为逗号,后跟一个数字和一个正斜杠),那么您需要做的就是使您的捕获组有条件(如上所示捕获原始数据) - 或 - 捕获这个新段。您可以通过在条件之间包含一个 OR(例如 \|
在基本正则表达式术语中)来做到这一点。
例如,在第一个捕获组的末尾添加 \|,[0-9]
,在第二个捕获组的末尾添加 \|[0-9][/]
,例如
$ sed 's/\([0-9][0-9]*:[0-9][0-9]*\|,[0-9]\)[ ]\([0-9][0-9]*:[0-9][0-9]*\|[0-9][/]\)/,/g' file
0/1:-1,-1,-1:146:28:14,14:4,0,0/1:-1,-1,-1:134:6:2,2:1,0
如果您的文件中有其他注意事项,我建议您 post 几行完整的输入,如果它们太长,则创建一个 zip、gzip、bzip 或 xz 文件并 post 将其添加到 pastebin 之类的网站,然后将 link 添加到您的问题中。
如果你现在真正关心的是,0 0/
中的space,那么你可以将sed
命令缩短为:
$ sed 's/\(,[0-9]\)[[:space:]]\([0-9][/]\)/,/g' file
0/1:-1,-1,-1:146:28:14,14:4,0,0/1:-1,-1,-1:134:6:2,2:1,0
(注意: 我已经包含了 [[:space:]]
来处理任何白色 space (space,制表符,...)在新示例中只是文字 [ ]
(space)
让我知道这是否解决了问题。
能否请您尝试以下。这将负责打印那些与正则表达式不匹配的值。此外,我们还可以通过 [0-9]+\.{4}
等方式使 match 中提到的正则表达式更短一些,因为这是在旧 awk 上测试的,所以无法测试它。
awk '
BEGIN{
OFS=","
}
match([=10=],/GT:GL:GOF:GQ:NR:NV [0-9]+:[0-9]+:[0-9]+:[0-9]+:[0-9]+/){
value=substr([=10=],RSTART!=1?1:RSTART,RSTART+RLENGTH-1)
value1=substr([=10=],RSTART+RLENGTH+1)
gsub(/[[:space:]]+/,",",value1)
print value,value1
next
}
1
' Input_file
perl myscript.pl '0/1:-1,-1,-1:146:28:14,14:4,0 0/1:-1,-1,-1:134:6:2,2:1,0'
myscript.pl,
#!/usr/local/ActivePerl-5.20/bin/env perl
my $input = $ARGV[0];
$input =~ s/ /\,/g;
print $input, "\n";
__DATA__
输出
0/1:-1,-1,-1:146:28:14,14:4,0,0/1:-1,-1,-1:134:6:2,2 :1,0
这将删除所有 space,而不仅仅是有问题的 space
我是编码新手,正在尝试格式化一些生物信息学数据。我试图用逗号删除 GT:GL:GOF:GQ:NR:NV
之后的所有空格,但不删除格式 xx:xx:xx:xx:xx
之外的任何内容(如示例)。我知道我需要使用 sed
和正则表达式选项,但我不太熟悉如何使用它。我以前从未真正使用过 sed
并且在尝试时感到困惑,因此我们将不胜感激。对不起,如果我的格式不好(这是我的第一个 post)。
编辑 2:这次我从文件中获得了实际数据,这可能有助于解决问题。删除了错误的例子。
新示例:我从我的实际文件中提取此数据(这只是两个示例),它被其他数据包围。本质上,该行有一堆数据,后跟 "GT:GL:GOF:GQ:NR:NV ",之后有更多格式如下所示的数据,最后还有一些随机数据。不幸的是,我无法 post 整行数据,因为它太长了,放不下。
输入
0/1:-1,-1,-1:146:28:14,14:4,0 0/1:-1,-1,-1:134:6:2,2:1,0
输出
0/1:-1,-1,-1:146:28:14,14:4,0,0/1:-1,-1,-1:134:6:2,2:1,0
我假设 xx:xx:xx
或 xx:xx:xx:xx
可以有任意数量的部分,因为有些有 3 个,有些有 4 个。
这很难用 sed
可靠地完成,因为它不支持环顾四周,这似乎是本例中可能需要的。
您可以尝试类似的方法:
perl -pe 's/(?<=\d) (?=\d+(:\d+){2,})/,/g' input.txt
如果你对 sed
有信心,你可以试试这个,但它可能会漏掉一些情况:
sed -r 's/(:[0-9]+) ([0-9]+:)/,/g' input.txt
您也可以在没有正则表达式的情况下使用 awk 实现您想要的结果:
awk '{printf "%s", FSFSFSFS","","; for (i=8;i<=NF;i++) printf "%s", FS$i; print ""}' input.txt
基本上,它从字段 1 到 5 使用默认字段分隔符 ("space") 输出,然后从字段 5 到 7 使用逗号分隔符,然后从字段 8 开始再次使用默认分隔符。
使用基本正则表达式,您可以使用字符类和反向引用来完成您的任务,例如
$ sed 's/\([0-9][0-9]*:[0-9][0-9]*\)[ ]\([0-9][0-9]*:[0-9][0-9]*\)/,/g' file
1/0 ./. 0/1 GT:GL:GOF:GQ:NR:NV 1:12:314,213:132:13:31,14:31:31 AB GT BB
1/0 ./. 0/1 GT:GL:GOF:GQ:NR:NV 10:13:12,41:41:1:13,13:131:1:1 AB GT RT
1/0 ./. 0/1 GT:GL:GOF:GQ:NR:NV 1:12:314,213:132:13:31,14:31:31 AB GT
基本上说:
- 查找并捕获任何
[0-9][0-9]*
一位或多位数字, - 由
:
和 分隔
- 后跟
[0-9][0-9]*
一个或多个数字 -- 作为捕获组 1, - 匹配捕获组 1 之后的 space 和捕获组 2(与捕获组 1 相同),
- 然后用逗号替换捕获组分隔符 space 使用反向引用 1 和 2(例如
</code> 和 <code>
)重新插入捕获组文本,最后 - 进行替换全局(例如
g
)以替换所有匹配项。
根据发布的新输入进行编辑
如果您仍然需要添加所有原始逗号, 和 您现在想要在 ,0 0/
之间添加一个逗号(逗号在单个 -数字后跟 space 替换为逗号,后跟一个数字和一个正斜杠),那么您需要做的就是使您的捕获组有条件(如上所示捕获原始数据) - 或 - 捕获这个新段。您可以通过在条件之间包含一个 OR(例如 \|
在基本正则表达式术语中)来做到这一点。
例如,在第一个捕获组的末尾添加 \|,[0-9]
,在第二个捕获组的末尾添加 \|[0-9][/]
,例如
$ sed 's/\([0-9][0-9]*:[0-9][0-9]*\|,[0-9]\)[ ]\([0-9][0-9]*:[0-9][0-9]*\|[0-9][/]\)/,/g' file
0/1:-1,-1,-1:146:28:14,14:4,0,0/1:-1,-1,-1:134:6:2,2:1,0
如果您的文件中有其他注意事项,我建议您 post 几行完整的输入,如果它们太长,则创建一个 zip、gzip、bzip 或 xz 文件并 post 将其添加到 pastebin 之类的网站,然后将 link 添加到您的问题中。
如果你现在真正关心的是,0 0/
中的space,那么你可以将sed
命令缩短为:
$ sed 's/\(,[0-9]\)[[:space:]]\([0-9][/]\)/,/g' file
0/1:-1,-1,-1:146:28:14,14:4,0,0/1:-1,-1,-1:134:6:2,2:1,0
(注意: 我已经包含了 [[:space:]]
来处理任何白色 space (space,制表符,...)在新示例中只是文字 [ ]
(space)
让我知道这是否解决了问题。
能否请您尝试以下。这将负责打印那些与正则表达式不匹配的值。此外,我们还可以通过 [0-9]+\.{4}
等方式使 match 中提到的正则表达式更短一些,因为这是在旧 awk 上测试的,所以无法测试它。
awk '
BEGIN{
OFS=","
}
match([=10=],/GT:GL:GOF:GQ:NR:NV [0-9]+:[0-9]+:[0-9]+:[0-9]+:[0-9]+/){
value=substr([=10=],RSTART!=1?1:RSTART,RSTART+RLENGTH-1)
value1=substr([=10=],RSTART+RLENGTH+1)
gsub(/[[:space:]]+/,",",value1)
print value,value1
next
}
1
' Input_file
perl myscript.pl '0/1:-1,-1,-1:146:28:14,14:4,0 0/1:-1,-1,-1:134:6:2,2:1,0'
myscript.pl,
#!/usr/local/ActivePerl-5.20/bin/env perl
my $input = $ARGV[0];
$input =~ s/ /\,/g;
print $input, "\n";
__DATA__
输出
0/1:-1,-1,-1:146:28:14,14:4,0,0/1:-1,-1,-1:134:6:2,2 :1,0
这将删除所有 space,而不仅仅是有问题的 space