Linux 只选择最后一个匹配模式

Linux 只选择最后一个匹配模式,linux,sed,Linux,Sed,我只想sed文本文件的最后一个匹配模式 输入文件: boy boy girl boy 输出文件: boy boy girl boys 一种方法是反转文件,只替换第一个匹配项,然后再次反转 tac <file> | sed '1 s/boy/boys/' | tac | sponge <newfile> tac | sed'1s/boy/boys/| tac |海绵 tac将“反向连接和打印文件”。海绵将“吸收标准输入并写入文件”。它在debian上的“moreut

我只想
sed
文本文件的最后一个匹配模式

输入文件:

boy
boy
girl
boy
输出文件:

boy
boy
girl
boys

一种方法是反转文件,只替换第一个匹配项,然后再次反转

tac <file> | sed '1 s/boy/boys/' | tac | sponge <newfile>
tac | sed'1s/boy/boys/| tac |海绵

tac将“反向连接和打印文件”。海绵将“吸收标准输入并写入文件”。它在debian上的“moreutils”包中。

您只需要
$

sed '$s/boy/boys/'
这可能适用于您(GNU-sed):

将文件拖到内存中,并使用贪婪替换所需字符串的最后一次出现

另一种内存占用较少的解决方案:

sed '/.*boy/,$!b;//{x;//p;x;h};//!H;$!d;x;s//&s/' file

这将使用保留空间保留包含所需字符串的前几行,并在遇到新出现的所需字符串时将其删除。在文件末尾,最后一次出现在保留空间中,并进行了修改。

tac>newfile
相比,将管道输送到
海绵
有什么好处?如果数据很大,缺点是有一个额外的管道,必须将数据复制进和复制出,这会减慢速度。这正是我思考问题时手指所做的,真的。我承认,这不是一个健壮的、多用途的解决方案。当我使用
tac>file
将它写回同一个文件时(因此
=
,预期的行为,如
sed-I
),结果是空的(即使它与stdout一起工作),所以我首先将它写回另一个文件,然后重命名它。也许有更好的解决办法,但对我来说很有效。假设在最后一个男孩之后还有另一个女孩?这适用于特定的示例数据,但不适用于更一般的情况。这是查找最后一个模式匹配的唯一解决方案,而不仅仅是在最后一行进行替换。
sed '/.*boy/,$!b;//{x;//p;x;h};//!H;$!d;x;s//&s/' file