首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >BASH_REMATCH空

BASH_REMATCH空
EN

Stack Overflow用户
提问于 2017-03-31 18:29:25
回答 2查看 5.6K关注 0票数 4

我正在尝试在Bash中捕获一些输入正则表达式,但是BASH_REMATCH是空的

代码语言:javascript
复制
#!/usr/bin/env /bin/bash
INPUT=$(cat input.txt)
TASK_NAME="MailAccountFetch"

MATCH_PATTERN="(${TASK_NAME})\s+([0-9]{4}-[0-9]{2}-[0-9]{2}\s[0-9]{2}:[0-9]{2}:[0-9]{2})"

while read -r line; do
    if [[ $line =~ $MATCH_PATTERN ]]; then
        TASK_RESULT=${BASH_REMATCH[3]}
        TASK_LAST_RUN=${BASH_REMATCH[2]}
        TASK_EXECUTION_DURATION=${BASH_REMATCH[4]}
    fi
done <<< "$INPUT"

我的意见是:

代码语言:javascript
复制
    MailAccountFetch                         2017-03-29 19:00:00  Success      5.0 Second(s)      2017-03-29 19:03:00

通过调试脚本(VS Code+Bash ext),当代码进入IF时,我可以看到输入字符串匹配,但是BASH_REMATCH没有填充两个捕获组。

我在听:

代码语言:javascript
复制
GNU bash, version 4.4.0(1)-release (x86_64-pc-linux-gnu)

有什么问题吗?

后期编辑

接受答案

接受最具解释性的答案。

最终解决了这个问题:

bashdb/VS代码环境导致空BASH_REMATCH。代码单独运行时运行正常。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-03-31 18:55:32

正如Cyrus在他的回答中所显示的那样,代码的简化版本--具有相同的输入--原则上可以在Linux上工作。

也就是说,代码引用捕获组、34**,和,而regex只定义 _2_.**。

换句话说,${BASH_REMATCH[3]}${BASH_REMATCH[4]}在定义上是空的。

但是,请注意,如果=~表示成功,BASH_REMATCH永远不会是完全空的:至少--在没有任何捕获组的情况下--将定义${BASH_REMATCH[0]}

有几点是值得提出来的:

  • 您的#!/bin/bash. shebang行读取#!/usr/bin/env /bin/bash,这实际上与相同。
代码语言:javascript
复制
- `/usr/bin/env` is typically used if you want a version _other_ than `/bin/bash` to execute, one you've installed later and put in the PATH (too):

#!/usr/bin/env bash

- 霍蒂指出,使用#!/usr/bin/env bash的另一个原因是也支持不太常见的平台,如FreeBSD,bash如果安装在/usr/local/bin中,则位于/usr/local/bin而不是通常的/bin中。

-在这两种情况下,执行哪个bash二进制文件都是不可预测的,因为它取决于调用时的有效$PATH值。

  • =~ 是platform-dependent:中为数不多的Bash特性之一,它使用平台regex库实现的特定regex方言。
代码语言:javascript
复制
- **`\s`** is a character class shortcut that is **not available on all platforms**, notably not on macOS; the **POSIX-compliant equivalent is** **`[[:space:]]`****.**
- (In your particular case, `\s` should work, however, because your Bash `--version` output suggests that you are on a Linux distro.)

  • 最好不要使用大写的shell变量名(如INPUT ),以便使用避免与环境变量和特殊shell变量发生冲突
票数 5
EN

Stack Overflow用户

发布于 2017-03-31 19:19:34

Bash使用系统库解析正则表达式,不同的解析器实现不同的特性。您遇到了regex类速记字符串不起作用的地方。请注意以下事项:

代码语言:javascript
复制
$ s="one12345   two"
$ [[ $s =~ ^([a-z]+[0-9]{4})\S*\s+(.*) ]] && echo yep; declare -p BASH_REMATCH
declare -ar BASH_REMATCH=()
$ [[ $s =~ ^([a-z]+[0-9]{4})[^[:space:]]*[[:space:]]+(.*) ]] && echo yep; declare -p BASH_REMATCH
yep
declare -ar BASH_REMATCH=([0]="one12345   two" [1]="one1234" [2]="two")

我也在macOS上这样做,但我在FreeBSD上也有同样的行为。

只需将\s替换为[[:space:]],将\d替换为[[:digit:]],等等,就可以了。如果您避免使用RE快捷方式,您的表达式将被更广泛地理解。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43147394

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档