bash - 如何对行组进行排序?

标签 bash sorting

在下面的例子中,有3个元素需要排序:

  1. [aaa]"和它下面的 4 行(总是 4 行)形成一个单元。
  2. [kkk]"和它下面的 4 行(总是 4 行)形成一个单元。
  3. [zzz]"和它下面的 4 行(总是 4 行)形成一个单元。

只有遵循这种模式的行组应该被排序; “[aaa]”之前和“[zzz]”第 4 行之后的任何内容都必须保持原样。

来自:

This sentence and everything above it should not be sorted.

[zzz]
some
random
text
here
[aaa]
bla
blo
blu
bli
[kkk]
1
44
2
88

And neither should this one and everything below it.

到:

This sentence and everything above it should not be sorted.

[aaa]
bla
blo
blu
bli
[kkk]
1
44
2
88
[zzz]
some
random
text
here

And neither should this one and everything below it.

最佳答案

也许不是最快的 :) [1] 但它会做你想做的,我相信:

for line in $(grep -n '^\[.*\]$' sections.txt |
              sort -k2 -t: |
              cut -f1 -d:); do
  tail -n +$line sections.txt | head -n 5
done

这是一个更好的:

for pos in $(grep -b '^\[.*\]$' sections.txt |
             sort -k2 -t: |
             cut -f1 -d:); do
  tail -c +$((pos+1)) sections.txt | head -n 5
done

[1] 第一个文件的行数类似于 O(N^2),因为它必须一直读到每个部分的部分。第二种,可以立即寻找到正确的字符位置,应该更接近O(N log N)。

[2] 这让您信守 promise ,每个部分中总是恰好有五行(标题加上后面的四行),因此 head -n 5。但是,如果有必要的话,用读到但不包括以“[”开头的下一行的内容替换它真的很容易。


保留开始和结束需要更多的工作:

# Find all the sections
mapfile indices < <(grep -b '^\[.*\]$' sections.txt)
# Output the prefix
head -c+${indices[0]%%:*} sections.txt
# Output sections, as above
for pos in $(printf %s "${indices[@]}" |
             sort -k2 -t: |
             cut -f1 -d:); do
  tail -c +$((pos+1)) sections.txt | head -n 5
done
# Output the suffix
tail -c+$((1+${indices[-1]%%:*})) sections.txt | tail -n+6

您可能想从中创建一个函数,或者一个脚本文件,将 sections.txt 整个更改为 $1。

关于bash - 如何对行组进行排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13521803/

相关文章:

mysql - 按首选平均值排序

linux - Bash:在脚本中执行多命令行字符串

bash - 使用 dockerfile 克隆私有(private) git 存储库

bash - 如何弄清楚为什么我的 shell 会崩溃?

Bash while 循环等待任务完成

python - 将值插入排序数组

javascript - 按属性值对对象数组进行排序

linux - 在 groovy 脚本中更改文件扩展名时执行 shell 命令时出现意外标记 '.'

c - 读取文本文件并对两个数组进行排序

Python 排序算法