匹配第 n 次出现的模式并删除,直到找到另一个多括号表达式模式

Matching pattern's nth occurence and delete until another multiple-brackets-expression pattern is found

我想编写一个 shell 脚本来匹配“%”字符并删除所有内容,直到找到特定字符。具体的字符范围在[A-G][a-g][m-n][p-s]括号内。 例如,我想将 %0.h2d 更改为 %d

到目前为止,我已经查看了很多解决方案,但没有找到我要找的东西,尤其是关于多个括号的问题。我对下面代码的最初计划是先隔离字符串,然后再进行删除:

awk '{for(i=1;i<=NF;i++) {if ($i == "%") beginning=i; if($i == [ A-G ] || $i ==    [ a-g ] || $i ==[ m-n ] || $i == [ p-s ]) ending=i }; for (j=beginning;j<=endin    g;j++) printf $j" ";printf "\n" }' .annex/file.c

我的代码语法不正确,我得到的是一堆警告:

awk: syntax error at source line 1
 context is
    {for(i=1;i<=NF;i++) {if ($i == "%") beginning=i; if($i == >>>  [ <<<
awk: illegal statement at source line 1
awk: illegal statement at source line 1`

% 被看到 n 次时,我如何修改此代码或使用另一个代码删除 %[A-G] || [a-g] || [m-n] || [p-s] 之间的内容?

尝试:

awk '{gsub(/%[^A-Ga-gm-np-s]+/, "%")} 1' .annex/file.c

例子

考虑这个输入文件:

$ cat file.c
fprintf(stdout,"%-20s %0.h2d",a,b)
fprintf(stderr,"%.3f",c)

让我们运行我们的命令:

$ awk '{gsub(/%[^A-Ga-gm-np-s]+/, "%")} 1'  file.c 
fprintf(stdout,"%s %d",a,b)
fprintf(stderr,"%f",c)

工作原理

gsub(/%[^A-Ga-gm-np-s]+/, "%") 查找匹配 % 后跟不在 A-Ga-gm-n 范围内的字符的任何字符串或 p-s 并将其替换为 %.

仅替换第 n 次出现

如果只想替换第 n 次出现,请尝试:

sed -E 'H;1h;$!d;x; s/%[^A-Ga-gm-np-s]+/%/'"$n"

例如,要替换第二次出现的情况,请使用:

$ n=2; sed -E 'H;1h;$!d;x; s/%[^A-Ga-gm-np-s]+/%/'"$n"  file.c
fprintf(stdout,"%-20s %d",a,b)
fprintf(stderr,"%.3f",c)

替换第三个:

$ n=3; sed -E 'H;1h;$!d;x; s/%[^A-Ga-gm-np-s]+/%/'"$n"  file.c
fprintf(stdout,"%-20s %0.h2d",a,b)
fprintf(stderr,"%f",c)

您可以使用任何您喜欢的 n 值。

工作原理

  • -E 告诉 sed 使用扩展正则表达式(awk 默认的那种)而不是基本正则表达式。

  • H;1h;$!d;x; 告诉 sed 将文件读入模式 space。

    这一系列命令读入整个文件。将此视为成语可能是最简单的。如果你真的想知道血淋淋的细节:

    • H - 追加当前行以保留 space
    • 1h - 如果这是第一行,覆盖保留 space 有了它
    • $!d - 如果这不是最后一行,删除模式 space 并跳转到下一行。
    • x - 交换保留和模式 space 以将整个文件放入 模式 space
  • 's/%[^A-Ga-gm-np-s]+/%/'"$n" 告诉 sed 替换第 n 次出现的模式。