需要一些 sed 魔法:将标记的行移动到文件的开头

Baa*_*rud 6 sed text-processing sort

我发现自己非常需要一些sed魔法(我真的需要坐下来学习这个)。我有一个包含很多行的文件。在查看之后,我通过在行的开头添加星号 (*) 来标记一些行。

我想用一些sed技巧(如果可能的话)做的是将所有标记的行移动到文件的开头(或结尾——我不挑剔),这样它们就形成了一个块。其他线路(未标记)应该不受干扰。

我怎样才能做这样的事情sed?我知道sed有一些用于移动文本的缓冲区...

cas*_*cas 12

sed 是必不可少的吗?如果你不介意两次通过源文件,这很容易用 grep 完成。

例如

grep '^\*' input > outputfile
grep -v '^\*' input >> outputfile
Run Code Online (Sandbox Code Playgroud)


mik*_*erv 9

根据文件的大小,您可以执行以下操作:

sed '/^*/!H;//p;$!d;g;s/\n//'
Run Code Online (Sandbox Code Playgroud)

那堆叠在H不匹配的旧空间行中/^*/。那些匹配的p会在输入中出现时被打印出来。然后从输出中删除所有!不是$最后一行的行d。在最后一行,我们g通过覆盖模式空间来保留空间,然后替换掉第一个\newline 字符s/\n//,因为第一H行每次都会产生一个额外的字符。

这需要一个大缓冲区,因为它已将所有这些行存储在H旧空间中。另一方面,这...

sed '/^*/p;$!d;g;r file' <file    |
sed -e '1,/^$/{/./p;d' -e '};/^*/d'
Run Code Online (Sandbox Code Playgroud)

……没有这个要求。

第一个sed print 只打印/^*/匹配的行,直到$最后一行,此时它打印一个空行,然后重新r读出整个输入文件。

第二个sed首先在从第一行到第一个空行的行范围内工作,p所有行至少匹配一个字符,然后d删除批次。在遇到第一个空行后,它会d删除所有匹配的行/^*/


slm*_*slm 6

您不需sed要这样做,您可以使用一些基本的 grep 将星号 (*) 行拉到顶部。比如说你有这个文件:

$ cat sample.txt 
1
2
3
4
* 5
* 6
* 7
8
9
10
Run Code Online (Sandbox Code Playgroud)

现在到grepsample.txt 文件,将星号 (*) 行放在首位:

$ cat <(grep '*' sample.txt) <(grep -v '*' sample.txt)
* 5
* 6
* 7
1
2
3
4
8
9
10
Run Code Online (Sandbox Code Playgroud)

上面将运行 2 个 grep,第一个拉出所有带星号的行,而第二个拉出所有未加星号的行。这 2 个命令的输出被重定向为cat使用<()符号的命令的输入。

替代方法

如果您不想使用 cat + 2 个子shell,您可以按照@terdon 的建议进行操作:

$ grep '*' sample.txt; grep -v '*' sample.txt
Run Code Online (Sandbox Code Playgroud)

这将拉出sample.txt包含星号 (*) 的所有行,然后是所有不包含星号的行。

参考