我正在尝试在Bash中捕获一些输入正则表达式,但是BASH_REMATCH是空的
#!/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"我的意见是:
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没有填充两个捕获组。
我在听:
GNU bash, version 4.4.0(1)-release (x86_64-pc-linux-gnu)有什么问题吗?
后期编辑
接受答案
接受最具解释性的答案。
最终解决了这个问题:
bashdb/VS代码环境导致空BASH_REMATCH。代码单独运行时运行正常。
发布于 2017-03-31 18:55:32
正如Cyrus在他的回答中所显示的那样,代码的简化版本--具有相同的输入--原则上可以在Linux上工作。
也就是说,代码引用捕获组、3、4**,和,而regex只定义 _2_.**。
换句话说,${BASH_REMATCH[3]}和${BASH_REMATCH[4]}在定义上是空的。
但是,请注意,如果=~表示成功,BASH_REMATCH永远不会是完全空的:至少--在没有任何捕获组的情况下--将定义${BASH_REMATCH[0]}。
有几点是值得提出来的:
#!/bin/bash. shebang行读取#!/usr/bin/env /bin/bash,这实际上与相同。- `/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方言。- **`\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.)
INPUT ),以便使用避免与环境变量和特殊shell变量发生冲突。发布于 2017-03-31 19:19:34
Bash使用系统库解析正则表达式,不同的解析器实现不同的特性。您遇到了regex类速记字符串不起作用的地方。请注意以下事项:
$ 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快捷方式,您的表达式将被更广泛地理解。
https://stackoverflow.com/questions/43147394
复制相似问题