Regex 如何调试传递给grep的(PCRE)正则表达式?

Regex 如何调试传递给grep的(PCRE)正则表达式?,regex,bash,shell,grep,pcre,Regex,Bash,Shell,Grep,Pcre,我正试图调试一个传递给grep的正则表达式,它似乎不适合我的系统 这是返回最新terraform版本的完整命令: wget -qO - "https://api.github.com/repos/hashicorp/terraform/releases/latest" | grep -Po '"tag_name": "v\K.*?(?=")' 这似乎对其他人有效,但对我无效。 在“tag\u name”之后添加一个*量词:以匹配额外的空格,这对我来说很有用: wget -qO - "https

我正试图调试一个传递给
grep
的正则表达式,它似乎不适合我的系统

这是返回最新terraform版本的完整命令:

wget -qO - "https://api.github.com/repos/hashicorp/terraform/releases/latest" | grep -Po '"tag_name": "v\K.*?(?=")'
这似乎对其他人有效,但对我无效。 在
“tag\u name”之后添加一个
*
量词:
以匹配额外的空格,这对我来说很有用:

wget -qO - "https://api.github.com/repos/hashicorp/terraform/releases/latest" | grep -Po '"tag_name": *"v\K.*?(?=")'
以下是来自
wget
的响应,无需管道连接到
grep

{
  "url": "https://api.github.com/repos/hashicorp/terraform/releases/20814583",
  "assets_url": "https://api.github.com/repos/hashicorp/terraform/releases/20814583/assets",
  "upload_url": "https://uploads.github.com/repos/hashicorp/terraform/releases/20814583/assets{?name,label}",
  "html_url": "https://github.com/hashicorp/terraform/releases/tag/v0.12.12",
  "id": 20814583,
  "node_id": "MDc6UmVsZWFzZTIwODE0NTgz",
  "tag_name": "v0.12.12",
  "target_commitish": "master",
  "name": "",
  "draft": false,
  "author": {
    "login": "apparentlymart",
    "id": 20180,
    "node_id": "MDQ6VXNlcjIwMTgw",
    "avatar_url": "https://avatars1.githubusercontent.com/u/20180?v=4",
    "gravatar_id": "",
    "url": "https://api.github.com/users/apparentlymart",
    "html_url": "https://github.com/apparentlymart",
    "followers_url": "https://api.github.com/users/apparentlymart/followers",
    "following_url": "https://api.github.com/users/apparentlymart/following{/other_user}",
    "gists_url": "https://api.github.com/users/apparentlymart/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/apparentlymart/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/apparentlymart/subscriptions",
    "organizations_url": "https://api.github.com/users/apparentlymart/orgs",
    "repos_url": "https://api.github.com/users/apparentlymart/repos",
    "events_url": "https://api.github.com/users/apparentlymart/events{/privacy}",
    "received_events_url": "https://api.github.com/users/apparentlymart/received_events",
    "type": "User",
    "site_admin": false
  },
  "prerelease": false,
  "created_at": "2019-10-18T18:39:16Z",
  "published_at": "2019-10-18T18:45:33Z",
  "assets": [],
  "tarball_url": "https://api.github.com/repos/hashicorp/terraform/tarball/v0.12.12",
  "zipball_url": "https://api.github.com/repos/hashicorp/terraform/zipball/v0.12.12",
  "body": "BUG FIXES:\r\n\r\n* backend/remote: Don't do local validation of whether variables are set prior to submitting, because only the remote system knows the full set of configured stored variables and environment variables that might contribute. This avoids erroneous error messages about unset required variables for remote runs when those variables will be set by stored variables in the remote workspace. ([#23122](https://github.com/hashicorp/terraform/issues/23122))"
}
使用我可以看到
“tag_name”:“v\K.*(?=”)
“tag_name”:*“v\K.*(?=”)
都与版本号正确匹配


所以我的系统肯定有问题,我只是很好奇为什么原来的系统不适合我,以及如何(如果可能的话)在这种情况下进行调试

很可能您的RegExp引擎不理解\K。RegExp有许多方言

使用标准PCRE regexp术语通常会在所有引擎中产生良好的结果

$ curl -s "https://api.github.com/repos/hashicorp/terraform/releases/latest" | egrep -oe '"tag_name": "v(.*)"'
"tag_name": "v0.12.12"
现在,如果您只需要版本号,则需要在之后获取这些数字(因为使用?!忽略模式可能并不总是有效)


我已经能够把范围缩小到以下几点。如果执行
wget
命令时没有管道grep,也没有格式化json响应:

wget -qO - "https://api.github.com/repos/hashicorp/terraform/releases/latest"
"html_url":"https://github.com/hashicorp/terraform/releases/tag/v0.12.12","id":20814583,"node_id":"MDc6UmVsZWFzZTIwODE0NTgz","tag_name":"v0.12.12","target_commitish":"master","name":"","draft":false
然后,我得到一个没有任何空格的json(我将在响应的一部分中只发布一个):

因此,原始正则表达式
“tag_name”:“v\K.*?(?=”
自然会失败,因为
后面没有空格:


这显然与传递给grep或grep本身的正则表达式无关。我不认为在这里深入研究响应本身有什么意义,因此可以认为原始问题已经解决(尽管如果有人知道可能是什么原因,请发表评论。)

使用jq解析JSON,grep无法理解JSON语法grep的确切版本是什么?@jhnc我的grep版本是
grep(GNU grep)3.1
@oguzismail我不需要解析json,我只是尝试获取包含版本号的匹配行并删除多余部分。在我看来,jq对于这类东西来说有点沉重,它并不是在每个系统上都可用,而grep很可能出现在大多数现代linux发行版上。无论如何,传递给grep的regex对其他人有效,但对我无效,所以这就是我在这里试图弄明白的。当我尝试运行给定的命令(也使用gnu grep 3.1)时,我得到了
0.12.12
。(尽管我会使用类似于
的“tag\u name”:“v\K[^”]*
;不需要前瞻)。我不知道为什么它对你不起作用,而对其他人却起作用。我不认为是这样。似乎我在
“tag\u name”:
“v0.12.12”
之间失去了一个空格。因为在空格工作后在正则表达式中添加限定符:
“tag_name”:*“v\K.*(?=”)
对我来说很好。除了删除它们之间的空格而不使用
*
限定符,例如:
“tag\u name”:“v\K.*(?=”)
在OpenBSD上,您的regexp不起作用。是我的在CentOS和FreeBSD上进行了测试,在那里也可以使用:PYou必须使用非常旧的pcre版本才能使其不支持
\K
。OpenBSD grep根本不支持pcre。难怪您尝试它时它不起作用(而且,即使它起作用了,您也没有使用
-P
来使用该方言,您使用的是使用posix扩展正则表达式的
egrep
),我不确定我们为什么要对此进行辩论?这是一个普遍有效的解决问题的方法。一个使用
jq
的好理由。。。它不关心json是如何格式化的(尽管我在尝试时得到了很好的打印,而不是像那样紧凑)jq-r'.tag|u name | ltrimstr(“v”)打印
0.12.12
。我同意在使用json时使用
jq
我自己。但这并不总是其他人的选择。如果你正在处理一些第三方的东西,他们可能不会那么开放地修改东西,包括依赖项,比如
jq
,当“某些东西不只能在我的机器上工作”时
"html_url":"https://github.com/hashicorp/terraform/releases/tag/v0.12.12","id":20814583,"node_id":"MDc6UmVsZWFzZTIwODE0NTgz","tag_name":"v0.12.12","target_commitish":"master","name":"","draft":false