您是否知道使用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中逃避正则表达式项。
答案 0 :(得分:0)
使用GNU sed:
sed -r 's/s(([^s]*s){2}[^s]*)$/S\1/' file
输出:
a declaration of Sovereignty need no witness
答案 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 个