【问题标题】:Sort lines in text file between patterns在模式之间对文本文件中的行进行排序
【发布时间】:2020-03-10 06:42:32
【问题描述】:

我正在尝试在 Bash 或 Python 中对模式之间的行进行排序。我想根据第二个字段以“,”作为分隔符对行进行排序。

给定以下文本输入文件:

Sample1
T1,64,0.65  MEDIUM
T2,60,0.45  LOW
T3,301,0.68  MEDIUM
T4,65,0.75  HIGH
T5,59,0.72  MEDIUM
T6,51,0.82  HIGH
Sample2
T1,153,0.77  HIGH
T2,152,0.61  MEDIUM
T3,154,0.67  MEDIUM
T4,283,0.66  MEDIUM
T5,161,0.65  MEDIUM
Sample3
T1,147,0.71  MEDIUM
T2,154,0.63  MEDIUM
T3,45,0.63  MEDIUM
T4,259,0.77  HIGH

我希望作为输出:

Sample1
T6,51,0.82  HIGH
T5,59,0.72  MEDIUM
T2,60,0.45  LOW
T1,64,0.65  MEDIUM
T4,65,0.75  HIGH
T3,301,0.68  MEDIUM
Sample2
T2,152,0.61  MEDIUM
T1,153,0.77  HIGH
T3,154,0.67  MEDIUM
T5,161,0.65  MEDIUM
T4,283,0.66  MEDIUM
Sample3
T3,45,0.63  MEDIUM
T1,147,0.71  MEDIUM
T2,154,0.63  MEDIUM
T4,259,0.77  HIGH

我已尝试调整 glenn jackman 在另一篇文章中的建议,但据我测试,它仅适用于 2 种模式:

> gawk -v cmd="sort -k2" p=1 '
>     /^PATTERN2/ {          # when we we see the 2nd marker:
>         close("cmd", "to");
>         while (("cmd" |& getline line) >0) print line 
>         p=1
>     }
>     p  {print}             # if p is true, print the line
>     !p {print |& "cmd"}   # if p is false, send the line to `sort`
>     /^PATTERN1/ {p=0}      # when we see the first marker, turn off printing ' FILE

【问题讨论】:

  • 您的预期输出似乎与您的排序说明不匹配(您的 sample2 部分似乎关闭。什么是 T8?为什么 T5 在 T3 之前?)。如有必要,请仔细检查并使用正确的值编辑您的问题。另外,你的文件有多大?您是否有时间限制,或者如果排序需要中等/长时间的时间可以吗?
  • 嗨@Aserre,关于 T3 之前的 T5,您是对的。我编辑了预期的输出。文件不大(45824 行)。 T[any digit] 是本实验中使用的 ID,不应影响排序过程。

标签: python awk sed


【解决方案1】:

您可以通过以下方式使用 GNU awk 执行此操作:

$ awk 'BEGIN{PROCINFO["sorted_in"]="@val_num_asc"; FS=","}
       /PATTERN/{
         for(i in a) print i
         delete a
         print; next
       }
       { a[$0]=$2 }
       END{ for(i in a) print i }' file

使用PROCINFO["sorted_in"]="@val_num_asc",我们告诉 GNU awk 以数组元素的值以数字升序出现的方式遍历数组。这个想法是创建一个数组,其中键为整行并为第二个字段赋值。我们不使用第二个字段作为键,因为可能有重复。然而,这仍然可以通过以下方式实现:

$ awk 'BEGIN{PROCINFO["sorted_in"]="@val_num_asc"; FS=","}
       /PATTERN/{
         for(i in a) print a[i]
         delete a
         print; next
       }
       ($2 in a){ a[$2]=a[$2] ORS $0; next }
       { a[$2] = $0 }
       END{ for(i in a) print a[i] }' file

【讨论】:

  • ++ 这是我打算发布的,但已经找到了你的答案
【解决方案2】:

请看下面的函数。

def sort_lines_by_second_field(source_filename: str, destination_filename: str):
    with open(source_filename) as source:
        lines = source.readlines()
        lines.sort(key=lambda row: int(row.split(',')[1]))
        with open(destination_filename, "w") as destination:
            destination.writelines(lines)

它读取所有行,按首先转换为整数的第二个字段对它们进行排序,然后将它们保存到目标文件中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-16
    • 2021-08-25
    • 1970-01-01
    相关资源
    最近更新 更多