sort命令用于对以特定单词开头的某些行进行排序

问题描述 投票:1回答:3

我想根据第二列对文件进行排序,但我也想只排序以“@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
bash
3个回答
2
投票

您可以通过读取两个不同的文件描述符并将排序的行替换为最终输出中的未排序行来执行您需要执行的操作。基本上,你可以利用'@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中执行上述操作并将输出重定向到文件来将输出重定向到单独的文件。仔细看看,如果您有任何其他问题,请告诉我。


0
投票

我还在学习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)

0
投票

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
© www.soinside.com 2019 - 2024. All rights reserved.