【问题标题】:Substituting multiple occurrences of a character inside a grep match在grep匹配中替换多次出现的字符
【发布时间】:2018-10-04 23:04:01
【问题描述】:

我正在尝试使用 TextWrangler 获取一堆文本文件,匹配一些尖括号标签中的所有内容(到目前为止一切都很好),并且对于 每个 匹配,替换所有出现的特定与另一个角色。

例如,我想采取类似的东西

xx+xx <f>bar+bar+fo+bar+fe</f> yy+y <f>fee+bar</f> zz

匹配&lt;f&gt;&lt;/f&gt; 中的所有内容,然后用* 替换所有+(但仅限“f”标签内)。

xx+xx <f>bar*bar*fo*bar*fe</f> yy+y <f>fee*bar</f> zz

我想我可以轻松地将包含 + 的“f”标签与类似的表达式匹配

<f>[^<]*\+[^<]*</f>

但我不知道如何为每个匹配项仅替换一个字符子类。我不知道每个标签中有多少个+。 我认为我应该为第一个正则表达式的所有匹配项运行一个正则表达式,但我不确定该怎么做。

(换句话说,我想匹配所有+,但只在特定的尖括号标签内)。

有人有提示吗?

非常感谢, 丹尼尔

【问题讨论】:

  • 这个问题真的是关于 UNIX 工具 grep 的标记,还是关于一些名为 TextWrangler 的工具中的同名功能?标记?
  • 嗨,老实说,两者都可以。如果我可以通过它的 grep 函数在 TextWrangler(我忘记标记 - 我会马上修复,抱歉)中做到这一点,那将是完美的。如果命令行“grep”(我在 OSX 上)还有另一种方法也可以工作......
  • UNIX grep 不是用来做替换的,而是用来做 g/re/p 的(它的名字有一个线索:-)),即它是为了全局查找一个正则表达式并打印匹配的字符串。如果您对此持开放态度,那么使用 awk 将是微不足道的。

标签: regex grep textwrangler


【解决方案1】:

如果您对 awk 解决方案感到满意:

$ awk '{
    while ( match($0,/<f>[^<]*\+[^<]*<\/f>/) ) {
        tgt = substr($0,RSTART,RLENGTH)
        gsub(/\+/,"*",tgt)
        $0 = substr($0,1,RSTART-1) tgt substr($0,RSTART+RLENGTH)
    }
    print
}' file
xx+xx <f>bar*bar*fo*bar*fe</f> yy+y <f>fee*bar</f> zz

以上内容可以在任何 UNIX 机器上的任何 shell 中使用任何 awk。它依赖于每个&lt;f&gt;...&lt;/f&gt; 中没有&lt;,如您的示例代码所示。如果可以将其包含在您的示例中,我们可以调整脚本来处理它:

$ awk '{
    gsub("</f>",RS)
    while ( match($0,/<f>[^\n]*\+[^\n]*\n/) ) {
        tgt = substr($0,RSTART,RLENGTH)
        gsub(/\+/,"*",tgt)
        $0 = substr($0,1,RSTART-1) tgt substr($0,RSTART+RLENGTH)
    }
    gsub(RS,"</f>")
    print
}' file
xx+xx <f>bar*bar*fo*bar*fe</f> yy+y <f>fee*bar</f> zz

【讨论】:

  • 谢谢,这是完美的。如果我需要替换两个字符,有没有办法调整它?例如。 + 和 * 和,比如说 - 和 _。 (在能够理解它的作用之前,我需要对其进行更多研究......)
  • 是的——既然你提到了它,我确实可以在 标签内有其他标签,比如 xx+yy+zz+ww。我想你的第二个例子应该解决这个问题(我不清楚 RS 究竟做了什么:它是否等同于 \n?)。再次感谢。
  • 第一个问题 - 当然,这只是软件,所以一切皆有可能。只需在现有 gsub() 行下添加一行 gsub(/-/,"_",tgt) 即可。对于您的第二个 - awk 读取由 RS 包含的任何值分隔的记录。它几乎总是\n,但有时是\r\n,有时是其他东西。在你的情况下,我假设 RS 是\n。因此,我将&lt;/f&gt; 替换为当前无法出现在记录中的字符(因为记录由RS 分隔),因此我可以在正则表达式[^\n]* 中否定该字符。无论RS 是单独的\n 还是\r\n,这都会起作用。
  • 谢谢,现在一切都清楚多了。最后一个问题:如果在我的标签之间我也允许有新行 \n 怎么办?我可以对 RS 进行不同的设置以避免混淆吗?
  • 您可以通过添加控制字符来破解它,并希望它们不会出现在您的数据中,但从那时起,对于 any 输入进行稳健处理并不是那么容易您需要弄清楚什么字符串可以分隔您的记录,并且根据您的 awk 版本,您可能会或可能不会对 RS 使用多字符字符串,并且有多种可能的解决方案。这不是什么大不了的事,但我们只需要看看您的数据到底是什么样子。
猜你喜欢
  • 2016-09-08
  • 1970-01-01
  • 2021-01-10
  • 2021-11-24
  • 1970-01-01
  • 2015-07-25
  • 2013-04-24
  • 1970-01-01
  • 2011-10-10
相关资源
最近更新 更多