【问题标题】:How do I convert from using `grep -P` to `grep -E`?如何从使用 `grep -P` 转换为 `grep -E`?
【发布时间】:2015-08-15 14:29:49
【问题描述】:

我有一个在 Ubuntu (Linux) 上使用的脚本,我想将其转换为在 Ubuntu (Linux) 和 MacOS X 上使用。Linux 上的 grep 与 FreeBSD 上的 grep 不同(即 MacOS X); MacOS X 上的grep 不支持-P 选项。不幸的是,在两个平台上使用-E 选项并没有给出相同的结果。考虑以下适用于 Linux 的代码:

wip_scenarios=$(grep -oP "^\d+ scenarios?" log/report.log | grep -oP "\d+")
echo "\n"
echo $wip_scenarios

这会在 Linux 上返回 0。用-E 替换所有-P 可以在MacOS X 上工作,但在Linux 上,这只会返回一个null,当我使用这样的条件时,这对我的脚本的其余部分没有帮助:

if [ $wip_scenarios != 0 ];then

一种解决方案是在前面放置一个标志并根据平台使用适当的选项集,但我希望有一个跨平台的解决方案。有没有办法做到这一点?

【问题讨论】:

  • 顺便说一句,[ $wip_scenarios != 0 ] 本身就有问题;必须是[ "$wip_scenarios" != 0 ]——引号不是可选的;将它们关闭可能会导致一些有趣的错误,具体取决于确切的值。
  • 顺便说一句,您希望scenarios 中的最后一个s 是可选的吗?这就是后面的? 正在做的事情;如果你想匹配文字?,最好的方法(恕我直言)是一个字符类:[[:digit:]]+ scenarios[?]
  • 另外,当你可以使用''时,不要使用"";使用"\d"'\d' 不同,因为在双引号中,序列被一些shell 扩展,仅替换为"d"
  • 参见 pubs.opengroup.org/onlinepubs/009604499/utilities/grep.html re: grep -o 也不是标准的一部分。
  • 感谢查尔斯的所有提示。我确实希望场景中的最后一个's'是可选的,所以?是故意的。

标签: linux macos ubuntu grep bsd


【解决方案1】:

对于您在此处提供的正则表达式,这很简单:将 \d 更改为 [[:digit:]]

因此:

wip_scenarios=$(grep -Eo '^[[:digit:]]+ scenarios[?]' <report.log | grep -Eo '[[:digit:]]+')

如果您的脚本以#!/bin/bash 开头(因此只能使用bash 运行),我还会考虑跳过对非标准扩展名grep -o 的依赖,而是依赖于bash 本身把你关心的数字分开:

# This works with any POSIX-compliant grep, but requires that the shell be bash
wip_scenarios_re='([[:digit:]]+) scenarios[?]'
wip_scenarios_line=$(grep -E '^[[:digit:]]+ scenarios[?]' <report.log)
[[ $wip_scenarios_line =~ $wip_scenarios_re ]] && {
  wip_scenarios=${BASH_REMATCH[1]}
}

【讨论】:

  • 我总是对阅读 bash 脚本的困难感到沮丧。我能理解你写的大部分内容,但你能帮我翻译一下吗? [[ $wip_scenarios_line =~ $wip_scenarios_re ]] &amp;&amp; { wip_scenarios=${BASH_REMATCH[1]} } 类似:“如果 wip_scenarios_line 匹配给定的正则表达式 wip_scenarios_re,那么...”?为什么是&amp;&amp;?这是什么意思?
  • 它的含义与在 C 或 Java 中的含义相同——它是一个短路布尔“and”。 a &amp;&amp; b 的副作用是仅在 a 为真时评估 b,因此它作为条件提供双重职责,其自身评估为表示两个命令是否成功的值..
  • 这是一个常见的 bash 脚本习语吗?我只是好奇,因为虽然我理解它,但它并没有特别可读。
  • 哪一部分?这里有很多成语。也就是说,可能令人惊讶的事情——比如在运行之前将正则表达式分配给一个字符串——是有原因的(在这种特殊情况下,与 =~ 语法稳定之前的旧版本 bash 的兼容性)。跨度>
  • 哦——你的意思是&amp;&amp;。是的,这是非常惯用的,不仅在 bash 中,而且在一般的 POSIX shell 中。 (现在,也有相关的反模式——例如,使用a &amp;&amp; b || c 表示if a; then b; else c; fi 的人正在招致错误。顺便说一句,同样的做法在 Python 世界中也曾经是一个问题,早在一个之前那里引入了-liner 条件语法)。
猜你喜欢
  • 2016-12-06
  • 2013-06-12
  • 1970-01-01
  • 2011-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多