替换每第n次出现的字符串

时间:2018-03-03 17:18:28

标签: bash unix awk sed replace

假设我有一个文本文件。我想使用sed替换文本文件中每第n次出现的字符串。如果我有一个字符串:

is this just real life or is this just fantasy or is it just me

对于'is'的每第3次出现,用'hat'替换,将给出输出

is this just real life or is this just fantasy or hat it just me

我尝试过使用其他StackOverflow问题提供的答案,但没有一个能够替换每一个问题。

7 个答案:

答案 0 :(得分:1)

使用 awk

<!DOCTYPE html>
<html>

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>

<body>

  <a href="#" id="myAnchor">Click here </a>

  <div id="someDiv">
    Hello World
  </div>

</body>

</html>

答案 1 :(得分:1)

你可以试试这个gnu sed

sed -E ':A;s/\bis/hat\n/3;x;G;h;s/(.*)\n.*/\1/;x;s/.*\n//;/\bis/bA;x;G;s/\n//g' infile

答案 2 :(得分:0)

关注awk可能对您有帮助。

awk -v occurence="3" -v val_string="this" '{for(i=1;i<=NF;i++){if(($i==val_string) && (i%occurence==0)){$i=toupper($i)}}} 1'  Input_file

此处还添加非单线形式的解决方案:

awk -v occurence="3" -v val_string="this" '
{
  for(i=1;i<=NF;i++){
    if(($i==val_string) && (i%occurence==0)){
    $i=toupper($i)}}
}
1
'  Input_file

输出如下。

this this THIS this this THIS this

您也可以在上面的代码中根据您的需要更改名为occurrenceval_string的变量的值。如果您想将输出保存到Input_file本身,请在上面的代码中连接> temp_file && mv temp_file Input_file

答案 3 :(得分:0)

awk 解决方案:

awk -v RS='[[:blank:]]+' 'NR % 3 == 0{ $0 = toupper($0) }
                         { printf "%s%s", (NR == 1? "": OFS), $0 }' file

输出:

this this THIS this this THIS this

答案 4 :(得分:0)

如果您使用sed扩展正则表达式(-E而非-e),则可以按如下方式重新表述问题。不要匹配“每隔三次出现”,而是认为您正在处理更长的字符串匹配

echo "is this just real life or is this just fantasy or is it just me" | sed -E 's/(is)(.*)(is)(.*)(is)/\1\2\3\4\hat/'

这适用于您的样本,但它也说明您的问题不完整;你想跨线,或只是在线内匹配?您是否希望将输入缓冲区视为单个长行,并将每三个“is”替换为其中,或者您是否在每行替换第三个“is”?所以这个例子是说明性的,但并不完整,只有sed的完整答案才会有一些真正的代码会试图避免的其他功能。

正则表达式方法可以生成疯狂且难以阅读的代码。如果由于某种原因无法运行awk,则可能还没有-E扩展的正则表达式标志。如果是我,我会使用awk。

答案 5 :(得分:0)

这可能适合你(GNU sed):

sed -r 's/is/\n&/g;/\n/!b;G;:a;;s/$/#/;s/#{3}$//;/\n$/s/\nis/\nhat/;s/\n//;/\n.*\n/ba;P;s/^.*\n//;h;d' file

我不赞成这个答案。有关详细说明,请参阅here

答案 6 :(得分:0)

从字面上看,它在其他答案中被忽略了。塞德(Sed)有能力做到这一点,而且不太冗长。

给出一个字符串:

"foo foo foo foo foo"

我们可以将以下sed表达式传递给目标对象:

sed -e 's/foo/bar/3'

第三次出现被替换:

echo "foo foo foo foo foo" | sed -e 's/foo/bar/3'
foo foo bar foo foo

您可以通过添加反表达式作为结束范围并全局替换(g)来定位范围。例如,将第二个替换为第四个:

echo "foo foo foo foo foo" | sed -e 's/foo/bar/g2' |sed -e 's/bar/foo/g4'
foo bar bar bar foo

现在这有点草率,并且可以使用'-r'开关将其压缩为多表达式sed语句:

echo "foo foo foo foo foo" | sed -re 's/foo/bar/g2' -e 's/bar/foo/g4'
foo bar bar bar foo

从第二个出现的“ foo”开始,第一个表达式将所有出现的“ foo”替换为“ bar”。从第四个出现的“ bar”开始,第二个表达式将所有出现的“ bar”都替换为“ foo”。

版本: GNU sed版本4.2.1

相关问题