【问题标题】:Using sed to replace numbers使用 sed 替换数字
【发布时间】:2012-09-21 15:12:43
【问题描述】:

我想用找到的数字计算的结果替换文件中的一些数字,并且想在 MacOSX 上使用 sed。我尝试了很多变体,现在知道我必须使用 -E 来使用现代而不是基本的正则表达式。

一些例子:

echo "bla 18934750 + wwv_flow_id.offset bla" | sed s/\ +\ wwv_flow_id.offset/blabla/

给予

bla 18934750blabla bla

因此,如果没有 -E,它会查找并替换固定文本。 但是使用 -E,它不会:

echo "bla 18934750 + wwv_flow_id.offset bla" | sed -E s/\ +\ wwv_flow_id.offset/blabla/

给予

bla 18934750 + wwv_flow_id.offset bla

换句话说:没有匹配,文本没有变化。 最终目标是找到固定文本“+ wwv_flow_id.offset”之前的数字并使用该数字并从中减去一个固定数字(例如750),因此最终结果变为:

bla 18934000 + wwv_flow_id.offset bla

为此,我至少需要反向引用,这也不能像我预期的那样工作,因为

echo "bla 18934750 + wwv_flow_id.offset bla" | sed -E s/\([0-9]+\)\ /\1/

给予

bla 1+ wwv_flow_id.offset bla

我希望一些正则表达式大师可以在这里帮助我。


更新

在 ruakh 的帮助下,这就是我现在所拥有的:

echo "bla 18934750 + wwv_flow_id.offset bla" | sed -E 's/([0-9]+) \+ wwv_flow_id.offset/(\1-750) \+ wwv_flow_id.offset/'

返回:

bla (18934750-750) + wwv_flow_id.offset bla

现在的额外问题是,如何把它变成

bla 18934000 + wwv_flow_id.offset bla




更新 2

通过将 sed 与 awk 结合起来,我设法达到了我想要的结果,如下所示:

echo "bla 18934750 + wwv_flow_id.offset bla" | sed -E 's/([0-9]+)([ ]*)\+([ ]*)wwv_flow_id.offset/~\1~\2\+\3wwv_flow_id.offset/' | awk -F~ '{print $1 $2-750 $3}'

(我确定原行中没有~ 标记)

【问题讨论】:

  • 请注意,扩展正则表达式使用() 进行分组,而不是\(\)。请记住引用您的 sed 脚本以保护它免受 shell 扩展。 awk 在这里会更容易使用。
  • Rob,我不认为 sed 是这里的最佳选择。您想匹配某些模式并对某些字段进行算术运算。为此,可以使用 awk 和 perl 等更好的工具。如果文件有一些固定的格式,它会很有帮助。
  • 感谢 ruakh、ik_zelf 和 Chuck Kollars 的所有帮助。我也使用 awk 发布了最终结果的第二次更新。可能会有更简单的解决方案,但我对这个很满意。

标签: regex macos sed


【解决方案1】:

在“现代”正则表达式中,+ 具有特殊含义——它表示“一个或多个”(就像 * 表示“零或多个”一样)——所以要匹配一个实际的加号,你需要使用\+。由于您显然不希望将 sed-script 用引号括起来,因此您可以将其写为 \\+:

echo "bla 18934750 + wwv_flow_id.offset bla" | sed -E s/\ \\+\ wwv_flow_id.offset/blabla/

虽然我认为如果你放弃这种偏好会让你的生活更轻松,然后写:

echo "bla 18934750 + wwv_flow_id.offset bla" | sed -E 's/ \+ wwv_flow_id.offset/blabla/'

引用您的论点还将解决您的反向引用问题,即 Bash 将 \1 转换为 1

echo "bla 18934750 + wwv_flow_id.offset bla" | sed -E 's/([0-9]+) /\1/'

但如果您仍然喜欢坚持使用非引用-sed-script 样式,您可以写\\1

echo "bla 18934750 + wwv_flow_id.offset bla" | sed -E s/\([0-9]+\)\ /\\1/

【讨论】:

  • 非常感谢 ruakh。这解决了这两个问题。关于奖金问题的任何想法(请参阅更新)?
  • @RobvanWijk: sed 不知道算术,只知道字符串操作。在您的示例中,您已将尾随 750 更改为尾随 000;您当然可以使用sed 实现这一目标。但是减去 750 的一般情况显然是不平凡的,你最好使用类似 awkperl 的东西。
  • Me too... 评估表达式并使用结果 [要么 (?{...}) 或修饰符 (小写) 'e'] 的正则表达式行为相当神秘,而且是大多数 RE 处理器都支持,包括 sed(甚至“现代”版本也不支持)。许多 Linux 系统已经有一个psed,所以你可以做类似 sed 的事情,除了真正使用 PERL REs 在幕后。 (否则,如果您需要在 RE 中进行算术运算,我建议您明确坚持使用 PERL。)
猜你喜欢
  • 1970-01-01
  • 2016-11-15
  • 1970-01-01
  • 2015-10-22
  • 2021-03-01
  • 1970-01-01
  • 2017-02-08
  • 2021-12-18
  • 2019-05-14
相关资源
最近更新 更多