文件如下(所有空格均为“单空格”):
A S1 0 0 0 -9 C C A G C C A G A A
B S2 0 0 0 -9 C C A G C C A G A A
C S3 0 0 0 -9 C C A G C C A G A A
D S4 0 0 0 -9 C C A G C C A G A A
我需要的是将每隔两列(偶数编号的字段)后面的空格替换为选项卡(\t
)。预期结果如下:
A S1"\t"0 0"\t"0 -9"\t"C C"\t"A G"\t"C C
B S2"\t"0 0"\t"0 -9"\t"C C"\t"A G"\t"C C
C S3"\t"0 0"\t"0 -9"\t"C C"\t"A G"\t"C C
D S4"\t"0 0"\t"0 -9"\t"C C"\t"A G"\t"C C
由于我的原始文件有更多的列数,因此命令行不应该是手动的 (指定一定数量的字段)。
我想就这个问题向大家请教一下。
感谢您事先的帮助。
答案1
匹配两个空格,保留一个并替换第二个:
sed -E 's/( [^ ]*) /\1\t/g'
答案2
基于强制awk
的解决方案;) :
awk '{for (i=1;i<=NF;i++) printf("%s%s",$i,i==NF?ORS:((i%2)?" ":"\t"))}' input.txt
这将迭代所有字段并通过 打印它们printf
,其中字段内容后跟
- 到达最后一个字段时的“输出记录分隔符”(默认为换行符)
- 否则,如果字段编号为奇数,则为空格,
\t
如果字段编号为偶数,则为 a
答案3
简短而愚蠢的方式,但完全合法,假设我们知道我们正在处理 16 列:
$ tr ' ' '\n' <file | paste -d ' \t' - - - - - - - - - - - - - - - -
A S1 0 0 0 -9 C C A G C C A G A A
B S2 0 0 0 -9 C C A G C C A G A A
C S3 0 0 0 -9 C C A G C C A G A A
D S4 0 0 0 -9 C C A G C C A G A A
这将用换行符替换每个原始空格分隔符。然后,它读取生成的流(每行一个字段),其中paste
将创建 16 列,其中包含交替的空格和制表符分隔符。
用于awk
打印制表符分隔的对中的字段:
$ awk -v OFS='\t' '{ nf = 0; delete a; for (i = 1; i < NF; i += 2) a[++nf]=sprintf("%s %s", $i, $(i+1)); $0 = ""; for (i = 1; i <= nf; ++i) $i = a[i]; print }' file
A S1 0 0 0 -9 C C A G C C A G A A
B S2 0 0 0 -9 C C A G C C A G A A
C S3 0 0 0 -9 C C A G C C A G A A
D S4 0 0 0 -9 C C A G C C A G A A
该代码在数组中临时存储以空格分隔的字段对a
。然后使用该数组的元素替换当前记录的字段。新记录以制表符作为分隔符打印,达到了预期的效果。
独立awk
代码:
BEGIN { OFS = "\t" }
{
nf = 0; delete a
for (i = 1; i < NF; i += 2)
a[++nf] = sprintf("%s %s", $i, $(i+1))
$0 = ""
for (i = 1; i <= nf; ++i)
$i = a[i]
print
}
答案4
使用itertools
来自的模块蟒蛇3标准库。
python3 -c 'import sys
from itertools import zip_longest
ifile = sys.argv[1]
fs,rs,ofs = " ","\n","\t"
with open(ifile) as f:
for l in f:
L = l.rstrip(rs).split(fs)
print(*[fs.join(filter(None,t))
for t in zip_longest(L[::2],L[1::2])],sep=ofs)
' your_file.input
Python 中的 zip 函数并行化两个或多个迭代器(在本例中为列表)。 Python 有一个紧凑的切片符号 [::2] 和 [1::2] 来引用给定列表中的偶数元素和奇数元素。在这里,我们从偶数 n 个奇数列表中各选择一个元素,并用空格将它们连接起来形成一对,然后连接这些对(又名,元组用Python来说)和制表符。
使用该gensub
函数GNU awk这允许我们在输入字符串中定位特定的匹配编号。
awk '
{
t=$0
for (i=2; i<NF; i++)
t = gensub(FS, "\t", i, t)
print t
}
' your_file.input
使用 sed 实用程序,我们首先将所有空格转换为换行符,该字符保证不会出现在模式空间中,在放入模式空间之前已被截断。然后我们逐步交替地将换行符更改为空格,将下一个换行符更改为制表符。重复直到换行符用完。
sed -e '
y/ /\n/
:a
s/\n/ /
s//\t/
t a
' your_file.input
Perl 中也是如此。
perl -lpe '
s/ /$|--?"\t":$&/eg;
$|-- unless $|--;
' your_file.input
perl -sF'\x20' -lane '
splice @F, $_, 2, "@F[$_,$_+1]" for 0 .. (@F>>1)-1;
print @F;
' -- -,=$'\t' your_file.input
```