例如,下面的代码可以...
[anony@mous-pc ~]$ (printf 'g?%s?m0\n' 008 006 004 002 ; printf 'wq\n') | ed -s file.txt
...取...内的所有数字
[anony@mous-pc ~]$ cat file.txt
005
003
110
069
002
008
004
245
009
007
006
...并将所需的数字(或其他字符串)移至顶部,但顺序相反执行的代码...
[anony@mous-pc ~]$ cat file.txt
002
004
006
008
005
003
110
069
245
009
007
...只要你给出相反的顺序,顺序就会是从第一个到最后(相反的顺序),或者...其他人可能会称之为从上到下格式化...所以再一次,实现从先到后我必须以这种方式执行最后一个命令......
[anony@mous-pc ~]$ (printf 'g?%s?m0\n' 008 006 004 002 ; printf 'wq\n') | ed -s file.txt
但是,如何才能按照从第一个到最后一个的顺序输入数字(或字符串),并且仍然实现从第一个到最后一个的顺序?
如果无法更改输入结果,是否
sed
可以更改输出结果并在保存之前翻转或反转它们file.txt
?
答案1
$ perl -lne '
/00[2468]$/ ? $h{$_} : $A[@A] = $_; }{
print for @h{qw/008 006 004 002/}, @A;
' file.txt
将匹配和不匹配的行存储在单独的容器中。当需要打印它们时,从键入哈希 %h 的匿名数组中提取顺序。
解释:
- 当我们读取每一行时,查看它是否包含匹配的行,即那些以 2、4、6 或 8 结尾的行。将它们存储在散列中,
%h
键是整个匹配行$h{$_}
。 - OTW,如果不匹配,则将不匹配的行推到数组的后面
@A
。 - 看到文件末尾后,我们
%h
首先打印哈希值。正如您所知,哈希值的访问本质上是随机的。但我们必须下达命令,因为这是你们的要求之一。因此,我们通过按照您希望键出现的顺序列出键来规定顺序:qw/008 006 004 002/
这是一个匿名数组。这将打印,$h{008}
然后$h{006}
等等。 - 之后
array @A
打印出包含不匹配行的内容。量子电动力学 - 现在,如果您要互换打印数组的顺序
@A
,hash slice @h{...}
您应该会看到匹配的元素向南而不是向北移动。 - 该代码仅打印到标准输出,您必须将其移回原始内容:
perl '...' file.txt > /tmp/file.txt; mv /tmp/file.txt file.txt
答案2
将要移动的行按照要移动的顺序移动到分隔线之后,然后将分隔线之后的所有行移动到文档的开头。
首先在编辑缓冲区的末尾插入一个空行并用例如标记它ka
:
a
.
ka
当最后一行是应移动的行之一时,插入新行作为分隔线而不是使用缓冲区的最后一行可以避免出现复杂情况。如果您计划移动空行,请在此特殊分隔线上插入一些独特的文本,例如---divider---
.
然后,按照您希望列出的顺序将每个匹配行从标记行上方移动到缓冲区的末尾:
1,'a- g/008/ m$
1,'a- g/006/ m$
1,'a- g/004/ m$
1,'a- g/002/ m$
请注意,要以相反的顺序获取行,请将每一行插入到标记行之后而不是缓冲区的末尾。您可以通过使用'a
而不是上面命令$
末尾的 at 来完成此操作。m
通过将标记行之后的所有行移动到缓冲区的开头并删除插入的分隔线来结束。
'a+,$ m0
$ d
(使用'a d
删除标记行将是自记录的,虽然$ d
更短,但要求您理解为什么最后一行是要删除的正确行。您也可以使用'a,$ m0
后跟,1 d
因为分隔线现在将是缓冲。)
将必要的命令输入ed -s
via printf
(最后两个命令打印缓冲区的行号并无条件退出编辑器):
{
printf '%s\n' a '' . ka
printf "1,'a- g/%s/ m$\n" 008 006 004 002
printf '%s\n' "'a+,$ m0" '$ d'
printf '%s\n' ,n Q
} | ed -s file.txt
上面的解决方案与 Perl 提出的解决方案本质上是相同的在另一个答案中,编辑缓冲区末尾的行扮演数组的角色@A
。