我想根据第二列对文件进行排序,但我也想只排序以“@SQ”开头的行,这意味着尚未排序的行必须保持与它们最初相同的位置。
sort -k 2,2 filename
输入:
@HD VN:1.0 SO:unsorted
@SQ SN:chr11 LN:197195432
@SQ SN:chr8 LN:181748087
@SQ SN:chr6 LN:181741298
@SQ SN:chr5 LN:111089233
@PL ID:Me RF:091284293
期望的输出:
@HD VN:1.0 SO:unsorted
@SQ SN:chr5 LN:111089233
@SQ SN:chr6 LN:181741298
@SQ SN:chr8 LN:181748087
@SQ SN:chr11 LN:197195432
@PL ID:Me RF:091284293
您可以通过读取两个不同的文件描述符并将排序的行替换为最终输出中的未排序行来执行您需要执行的操作。基本上,你可以利用'@SQ'
的版本排序功能,例如sort -V
,从grep '^@SQ' <filename.txt | sort -V
开始隔离和排序行。
stdin
然后,您可以通过读取第二个文件描述符逐行读取原始文件,从而可以读取while read -r line <&3; do
...
read -r sorted
...
done 3<"filename.txt"
上面排序行的输出,例如:低于FD 3读数,
read
(请注意,如果您的-r
版本未提供grep '^@SQ' <filename.txt | sort -V |
while read -r line <&3; do
if [ "${line%% *}" = '@SQ' ]; then ## line begins with '@SQ'
read -r sorted
echo "$sorted"
else
echo "$line"
fi
done 3<"filename.txt"
选项,请将其删除)
将这两个部分组合在一起,您可以:
dat/sortdata.txt
我将未分类的文件存储在$ grep '^@SQ' <dat/sortdata.txt | sort -V |
> while read -r line <&3; do
> if [ "${line%% *}" = '@SQ' ]; then ## line begins with '@SQ'
> read -r sorted
> echo "$sorted"
> else
> echo "$line"
> fi
> done 3<"dat/sortdata.txt"
@HD VN:1.0 SO:unsorted
@SQ SN:chr5 LN:111089233
@SQ SN:chr6 LN:181741298
@SQ SN:chr8 LN:181748087
@SQ SN:chr11 LN:197195432
@PL ID:Me RF:091284293
中的位置。您可以获得所需的输出:
示例使用/输出
#!/usr/bin/python3
from natsort import natsorted
import re
insq = False
sq = []
r = re.compile( r"^@SQ")
with open( "franchini", "r" ) as f:
for line in f:
if not r.match( line ):
if insq:
for i in natsorted(sq):
print(i)
print( line.strip() )
insq = False
else:
sq.append( line.strip() )
insq = True
如果您愿意,可以通过在子shell中执行上述操作并将输出重定向到文件来将输出重定向到单独的文件。仔细看看,如果您有任何其他问题,请告诉我。
我还在学习python,所以我不会声称它很漂亮或有效,但它确实有效。
./fran.py
@HD VN:1.0 SO:unsorted
@SQ SN:chr5 LN:111089233
@SQ SN:chr6 LN:181741298
@SQ SN:chr8 LN:181748087
@SQ SN:chr11 LN:197195432
@PL ID:Me RF:091284293
这保存为fran.py,您在franchini中的样本数据给出以下结果:
import re, sys
with open(sys.argv[1], 'r') as f:
lines = f.read().splitlines()
sq_lines = []
for l in lines:
if l.startswith('@SQ'):
sq_lines.append(l)
else:
if sq_lines:
processed = sorted(sq_lines, key=lambda l: int(re.split(r'(\s+)', l)[2][6:]))
print('\n'.join(i for i in processed))
print(l)
Potkhon Solyuion:
sort_sq_lines.py脚本:
python sort_sq_lines.py filename
用法:
@HD VN:1.0 SO:unsorted
@SQ SN:chr5 LN:111089233
@SQ SN:chr6 LN:181741298
@SQ SN:chr8 LN:181748087
@SQ SN:chr11 LN:197195432
@PL ID:Me RF:091284293
输出:
qazxswpoi