Bash 通过Sed替换行尾的第n个引用

Bash 通过Sed替换行尾的第n个引用,bash,sed,Bash,Sed,您是否知道一种更好或更简单的方法,可以使用sed或Bash从一行末尾最后一次出现的正则表达式匹配中替换,而无需使用rev 下面是匹配字母“s”最后出现的第三个字母的rev方法–仍然是正向匹配,但利用rev匹配最后一个字符 echo "a declaration of sovereignty need no witness" | rev | sed 's/s/S/3' | rev a declaration of Sovereignty need no witness 更新——基于Cyruses

您是否知道一种更好或更简单的方法,可以使用sed或Bash从一行末尾最后一次出现的正则表达式匹配中替换,而无需使用
rev

下面是匹配字母“s”最后出现的第三个字母的
rev
方法–仍然是正向匹配,但利用
rev
匹配最后一个字符

echo "a declaration of sovereignty need no witness" | rev | sed 's/s/S/3' | rev
a declaration of Sovereignty need no witness
更新——基于Cyruses答案的通用解决方案:

SEARCH="one" 
OCCURRENCE=3 
REPLACE="FOUR" 
SED_DELIM=$'\001'  
SEARCHNEG=$(sed 's/./[^&]*/g' <<< "${SEARCH}")
sed -r "s${SED_DELIM}${SEARCH}((${SEARCHNEG}${SEARCH}){$((${OCCURRENCE}-1))}${SEARCHNEG})\$${SED_DELIM}${REPLACE}\1${SED_DELIM}"  <<< "one one two two one one three three one one"
SEARCH=“一”
发生率=3
替换=“四个”
SED_DELIM=$'\001'
SEARCHNEG=$(sed's//[^&]*/g'与GNU sed:

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

a declaration of Sovereignty need no witness 主权宣言不需要证人
请参阅:

使用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"

您首先需要计算发生的事件数量,并确定要替换的事件:

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/'


在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}
    是重复的次数,也就是说,我们希望在要替换的一个s之后有两个s

谢谢,这适用于我用作示例的单个字母,但适用于单词regex
[^s]
-->
[^importantword]
将无法按预期匹配。匹配结束锚是一个有效的概念。要匹配
重要词汇,请首先将所述单词减少为唯一的单个字符,然后如上所述进行匹配,然后恢复未更改的单词。
str="\(.*importantword.*\)"
echo "importantword1 importantword2 importantword3 importantword4 importantword5 importantword6" | 
   sed 's/\('${str}'\{'$l'\}\)importantword\('${str}'\{'$r'\}\)/\1ExportAntword\3/'
echo "a declaration of sovereignty need no witness" \
| perl -pe 's/s(?=(?:[^s]*s[^s]*){2}$)/S/'