替换文件中出现的最后一个单词

替换文件中出现的最后一个单词

场景是我想使用 注释掉 shell 脚本中最后一次出现的单词sed

假设我有temp.sh以下内容:

Abc 123 Abc
Sdf 2
Abc
Abc
Utyr
Qww

我想将最后一个实例Abc(发生在行的开头)替换为#Abc 所以最后,结果将是这样的:

Abc 123 Abc
Sdf 2
Abc
#Abc
Utyr
Qww

答案1

反转文件,注释掉第一个,然后再次反转文件:

$ tac temp.sh | sed '0,/^Abc/{s/^Abc/#&/}' | tac
Abc 123 Abc
Sdf 2
Abc
#Abc
Utyr
Qww

这意味着“从第 0 行开始,继续直到第一行匹配/^Abc/,并且仅在这些行中,替换Abc#以及匹配的任何内容 ( #),在本例中为Abc。感谢这个答案

请注意,这需要tac一个 GNU 工具以及 的 GNU 实现sed

要对原始文件进行更改,请使用:

tac temp.sh | sed '0,/^Abc/{s/^Abc/#&/}' | tac > temp1.sh &&
  mv temp1.sh temp.sh

或者,在 Perl 中:

$ tac temp.sh | perl -pe 'next if $k; $k++ if s/^Abc/#$&/ ' | tac
Abc 123 Abc
Sdf 2
Abc
#Abc
Utyr
Qww

要对原始文件进行更改,请使用:

tac temp.sh | perl -pe 'next if $k; $k++ if s/^Abc/#$&/ ' | tac> temp1.sh &&
  mv temp1.sh temp.sh

或者使用Stephane 的纯粹perl方法或者善行清净sed,两者都用于-i编辑原始文件。

答案2

$ sed -e 'H; $!d' -e 'g; s/\n\(.*\n\)\(Abc\)/\1#\2/' file
Abc 123 Abc
Sdf 2
Abc
#Abc
Utyr
Qww

这会将整个文件读取到 的保留空间中sed,对其进行修改并输出修改后的文本。

前两个sed表达式H$!d,将每一行附加到保留空间,然后跳到下一个循环(除非我们处于输入的最后一行)。

g命令针对最后一行执行并获取保留空间的内容。然后,替换会删除其中的初始换行符(将第一行附加到空保留空间),并#在最后一次出现换行符之前Abc插入一个字符。

我们保证得到最后的 Abc在换行符之后,因为.*是贪婪的,因此会尽可能匹配。

您可以使用-i就地编辑文件(使用 GNU sed,使用 BSDsed则需要-i '.bak'):

sed -i'.bak' -e 'H; $!d' -e 'g; s/\n\(.*\n\)\(Abc\)/\1#\2/' file

ed编辑:

$ printf '%s\n' '1;?^Abc?;s//#&/' ,p Q | ed -s file
Abc 123 Abc
Sdf 2
Abc
#Abc
Utyr
Qww

ed这本质上是使用单个编辑命令来执行编辑1;?^Abc?;s//#&/。该命令首先将光标移动到文件的第一行(1;如果字符串Abc位于最后一行,则这是必要的),然后向后搜索^Abc文件中正则表达式的最后一个匹配项(?^Abc?)。一旦找到,它就会#在找到的行的开头插入一个字符(s//#&/;这会重用最近匹配的正则表达式,并用于&在之后插入该行的匹配部分#)。

尾随的,pandQ命令将整个缓冲区打印到标准输出,然后无条件退出。

答案3

awk(无管道):
awk -v str=Abc '
    NR==FNR{if ($0 == str) nr_str=NR; next}
     {print (FNR == nr_str) ? "#"$0 : $0}
' file file
输出
Abc 123 Abc
Sdf 2
Abc
#Abc
Utyr
Qww

答案4

使用awk

反转文件,使用thenawk的函数。sub()之后再次反转文件会给出预期的输出。

$ tac file |
awk '/^Abc/ && (!found){sub(/^Abc/, "#Abc"); found++}1' |
tac

输出

Abc 123 Abc
Sdf 2
Abc
#Abc
Utyr
Qww

不带管道:

$ awk '
  BEGIN{rec_rep=""; rec_last=""}
       {if (/^Abc/){ 
                   if (rec_rep) print rec_rep;
                                rec_rep = $0;
                                sub(/^Abc/, "#Abc"); 
                                rec_last = $0; 
                                }
          
                   else {       rec_rep = ((rec_rep) ? rec_rep ORS : "") $0;
                                rec_last = ((rec_last) ? rec_last ORS : "") $0 }
  }
  END{print rec_last}' file

相关内容