如何仅使用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
在某些文件中,块的开头用斜杠标记,如上例所示。在其他情况下,块仅通过它们之间存在一个或多个空行来标记。
答案 0 :(得分:4)
在emacs
中,您可以使用sort-paragraphs
命令:
CTRL-X ħ 元X 排序段落 输入 < / p>
vim
:https://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
将数据转换为csv
,然后sort
csv
,最后我将csv
转换回列表样式。
/Section 1/
Dogs
Rabbits
Lemmings
/Section 2/
Eagles
Mice
/Section 3/
Rabbits
Dogs
Cats
修改:抱歉,我没有仔细查看您的问题。您可以将sort
命令更改为tac
以撤销订单。
答案 1 :(得分:3)
如果有空白行分隔所有块,
awk 'BEGIN{ORS=RS RS;RS=""}{a[NR]=$0}END{for(i=NR;i>0;i--)print a[i]}'
答案 2 :(得分:1)
使用csplit
将它们拆分为单独的文件,将生成的文件名放入另一个文件中,然后使用tac
获取要合并的文件名。
答案 3 :(得分:0)
您示例中的块之间有什么区别? 2个换行符。在Emacs Lisp中,如果文本是字符串,如果安装dash
和s
,则可以使用以下两个等效表达式之一:
(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 pipes: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
表示的参数中。例如。如果nreverse
的结果为X
,则等效值为(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