使用 awk 或 grep 捕获组

使用 awk 或 grep 捕获组

我想循环遍历找到的每个模式,并可以访问循环内的不同捕获组,可能使用grepor awk(如果可能的话,我想坚持使用它们,以避免学习第三个模式,但如果确实有必要,我会再学一个!)

做类似的事情:

awk-or-grep -E '(blah(.*)hello=(.*))' sampletext | while read -r l; do 
    echo $0             #1st capture group
    echo $1             #2nd catpure group
    dosomethingwith $2  #3rd capture group
done

存在?


示例文本:

blah12687hello=123
nothingthatmatches
blah3211hello=123456
blah15butnottheotherpattern

使用前面提到的循环,它应该输出:

blah12687hello=123
12687
<it should run the command dosomethingwith 123>
blah3211hello=123456
3211
<it should run the command dosomethingwith 123456>

答案1

shellbash本身提供了一种根据方便需要对捕获的组进行正则表达式匹配处理的方法。

=~双括号内的运算符测试表达式,匹配[[字符串位于运算符左侧,正则表达式作为右侧操作数。

if [[ "$str" =~ $re ]]; then

如果表达式与字符串匹配,则字符串的匹配部分存储在数组中BASH_REMATCH,可以循环访问各个捕获的组。退出状态是0正则表达式是否匹配、1不匹配以及2表达式是否无效。


就您的示例而言,假设您将输入行存储在数组中,并且单词blahhello是固定模式

#!/usr/bin/env bash

exampleStr=('blah12687hello=123' 'nothingthatmatches' 'blah3211hello=123456' 'blah15butnottheotherpattern')

re='blah([[:digit:]]+)hello=([[:digit:]]+)'

for str in "${exampleStr[@]}"; do
    if [[ "$str" =~ $re ]]; then
       for group in "${BASH_REMATCH[@]}"; do
           printf "%s\n" "$group"
       done
    else
       printf "No match \n"
    fi
done

正如您在上面的代码中看到的,一旦我们将正则表达式匹配为 true,我们就可以循环数组BASH_REMATCH以打印每个捕获的组。整体脚本输出类似于

blah12687hello=123     # Value of BASH_REMATCH[0]
12687                  # Value of BASH_REMATCH[1]
123                    # Value of BASH_REMATCH[2]
Regex not matches.
blah3211hello=123456
3211
123456
Regex not matches.

正如您所看到的,BASH_REMATCH[0]始终包含正则表达式成功匹配的字符串部分,并且可以从索引开始访问各个捕获的组1。您可以编写自定义逻辑来处理每个捕获的组,这正是您最初打算执行的操作。


如果您有兴趣读取文件输入,只需while在要处理的文件上使用带有输入重定向的循环

while IFS= read -r line; do
    if [[ "$line" =~ $re ]]; then
       for group in "${BASH_REMATCH[@]}"; do
           printf "%s\n" "$group"
       done
    else
       printf "No match \n"
    fi
done < inputFile.txt

相关内容