11

如何仅使用 sed 和 cat 之类的 bash 命令来恢复某些文本块的顺序?我想要的是类似 tac 的东西,但不是逐行操作,而是逐块操作。例子:

/Section 3/
Rabbits
Dogs
Cats

/Section 2/
Eagles
Mice

/Section 1/
Dogs
Rabbits
Lemmings

/Section 1/
Dogs
Rabbits
Lemmings

/Section 2/
Eagles
Mice

/Section 3/
Rabbits
Dogs
Cats

在某些文件中,块的开头用斜杠标记,如上例所示。在其他情况下,这些块仅通过它们之间存在一个或多个空行来标记。

4

4 回答 4

4

emacs中,您可以使用以下sort-paragraphs命令:

Ctrl-xhMeta-xsort-paragraphsEnter


vimhttps ://superuser.com/questions/365094/sort-file-per-paragraph-in-vim


使用基本的 unix 工具:

awk -F'\n' -vRS='' -vOFS=',' '{$1=$1}1' input.txt |
    sort |
        tr ',' '\n' |
            sed 's@^/@\n/@'

我使用awk将数据转换为 a csv,然后sortcsv,最后我将其转换csv回列表样式。


结果:

/Section 1/
Dogs
Rabbits
Lemmings

/Section 2/
Eagles
Mice

/Section 3/
Rabbits
Dogs
Cats

编辑:对不起,我没有仔细看你的问题。您可以将sort命令更改tac为反转顺序。

于 2012-06-03T23:13:31.000 回答
3

如果有空行分隔所有块,

awk 'BEGIN{ORS=RS RS;RS=""}{a[NR]=$0}END{for(i=NR;i>0;i--)print a[i]}'
于 2012-06-04T00:39:45.930 回答
1

用于csplit将它们拆分为单独的文件,将生成的文件名放入另一个文件中,然后用于tac获取要合并的文件名。

于 2012-06-03T23:14:20.657 回答
1

在您的示例中,块之间的区别是什么?2个换行符。在 Emacs Lisp 中,如果文本在字符串中,如果安装dashand s,则可以使用以下 2 个等效表达式之一:

(s-join "\n\n" (nreverse (s-split "\n\n" s))) ; where s is your string
(->> s (s-split "\n\n") nreverse (s-join "\n\n"))

->>是破折号的线程宏,它s通过连续的函数调用。想想*nix 管道s | s-split "\n\n" | nreverse | s-join "\n\n"

如果你想要一个 Emacs Lisp 函数来打开一个文件,反转块然后将它保存回相同的文件,你也可以安装f文件操作库:

(defun reverse-blocks (f)
  "F is a filename."
  (interactive "fFind file: ") ; letter `f` is filename goes in first arg
  (let ((s (f-read f))) ; read file into a string
    (--> s
         s-chomp ; remove trailing newline
         (s-split "\n\n" it)
         nreverse
         (s-join "\n\n" it)
         (f-write it 'utf-8 f)))) ; write to the same file

在这里,我使用了另一个尾随宏-->,它允许将前一个计算的结果放在表示it下一个计算的参数中。例如,如果 的结果nreverseX,那么等价的就是(s-join "\n\n" X)。最后,假设您不仅要反转,而且要根据单词“Section”后面的数字对块进行排序:

(--sort (< (string-to-number (cadr (s-match "/.*?\\([0-9]\\)/" it)))
           (string-to-number (cadr (s-match "/.*?\\([0-9]\\)/" other))))
        it) ; put it instead of nreverse

其中,使用dash-functional相当于:

(--sort (-on '<
             (-compose 'string-to-number
                       'cadr
                       (-partial 's-match "/.*?\\([0-9]+\\)/")))
        it) ; put it instead of nreverse

阅读dash文档以了解 、-on-compose-partial什么。

于 2015-02-18T20:14:43.260 回答