通过Sed替换从行尾的第N次出现

时间:2016-03-27 19:10:49

标签: bash sed

您是否知道使用sed或Bash更好或更简单的方法来替换最后一次出现的正则表达式匹配而不使用% cat file string 123 string 1 string string string 456 string % perl -ne 'BEGIN{my $x} $x += () = /[0-9]+/g; END{print($x . "\n")}' file 3 %

以下rev方式匹配字母's'的最后一次出现的第三种方式 - 仍然向前匹配,但是使用rev来匹配最后一个字符。

rev

更新 - 基于Cyruses答案的通用解决方案:

echo "a declaration of sovereignty need no witness" | rev | sed 's/s/S/3' | rev
a declaration of Sovereignty need no witness

注意:要真正通用,它应该从LHS中逃避正则表达式项。

4 个答案:

答案 0 :(得分:0)

使用GNU sed:

sed -r 's/s(([^s]*s){2}[^s]*)$/S\1/'  file

输出:

a declaration of Sovereignty need no witness

请参阅:The Stack Overflow Regular Expressions FAQ

答案 1 :(得分:0)

使用awk:

str='a declaration of sovereignty need no witness'

awk -v r='S' -v n=3 'BEGIN{FS=OFS="s"} {
   for (i=1; i<=NF; i++) printf "%s%s", $i, (i<NF)?(i==NF-n?r:OFS):ORS}' <<< "$str"

<强>输出:

a declaration of Sovereignty need no witness

答案 2 :(得分:0)

首先需要计算出现次数并找出要替换的出现次数:

echo "importantword1 importantword2 importantword3 importantword4 importantword5 importantword6" | 
    grep -o "importantword" | wc -l

将它用于你的sed字符串

echo "importantword1 importantword2 importantword3 importantword4 importantword5 importantword6" |
   sed 's/\(\(.*importantword.*\)\{3\}\)importantword\(\(.*importantword.*\)\{2\}\)/\1ExportAntword\3/'
importantword1 importantword2 importantword3 ExportAntword4 importantword5 importantword6

您可以通过设置左右变量获得相同的答案:

l=3
r=2
echo "importantword1 importantword2 importantword3 importantword4 importantword5 importantword6" |
  sed 's/\(\(.*importantword.*\)\{'$l'\}\)importantword\(\(.*importantword.*\)\{'$r'\}\)/\1ExportAntword\3/'

str="\(.*importantword.*\)"
echo "importantword1 importantword2 importantword3 importantword4 importantword5 importantword6" | 
   sed 's/\('${str}'\{'$l'\}\)importantword\('${str}'\{'$r'\}\)/\1ExportAntword\3/'

答案 3 :(得分:0)

在Perl中,您可以使用前瞻性断言:

echo "a declaration of sovereignty need no witness" \
| perl -pe 's/s(?=(?:[^s]*s[^s]*){2}$)/S/'
  • (?=...)是前瞻性断言,表示“如果后跟...”,但...部分不匹配,因此未替换
  • [^s]*s[^s]*意味着只有一个s可能被非s es包裹
  • {2}是重复次数,即我们希望在要替换的字母之后添加 2