2016-12-14 105 views
7

我有一个正则表达式模式,应该匹配在字符串中的多个地方。我想将所有的匹配组合成一个数组,然后打印每个元素。Bash正则表达式不匹配匹配

所以,我一直在尝试这样的:

#!/bin/bash 

f=$'\n\tShare1 Disk\n\tShare2 Disk\n\tPrnt1 Printer' 
regex=$'\n\t(.+?)\\s+Disk' 
if [[ $f =~ $regex ]] 
then 
    for match in "${BASH_REMATCH[@]}" 
    do 
     echo "New match: $match" 
    done 
else 
    echo "No matches" 
fi 

结果:

New match: 
    Share1 Disk 
    Share2 Disk 
New match: Share1 Disk 
    Share2 

预期的结果将是

New match: Share1 
New match: Share2 

我认为这是行不通的,因为我的.+?匹配贪婪。所以我看了这是如何用bash正则表达式来完成的。但似乎每个人似乎都建议使用perl正则表达式来使用grep。

但一定有另一种方式。我想也许是这样[^\\s]+ ..但输出那是:

New match: 
    Share1 Disk 
New match: Share1 

... 任何想法?

+0

一个想法是使用'[^ \\ S] +'呢? '。+?'。这将匹配字符,直到找到空白。 – Rahul

+0

@Rahul或'\ S +?' –

+0

两者的结果都与我在问题中已经提到的'[^ \ s] +'相同。我不认为'''在bash中甚至是被支持的,我的意思是在这个上下文中。我的意思是''后面的'+'通常意味着'match ungreedy'。 – Forivin

回答

5

这里有几个问题。首先,BASH_REMATCH的第一个元素是匹配模式的整个字符串,而不是捕获组,因此您希望使用${BASH_REMATCH[@]:1}来获取捕获组中的那些内容。

但是,bash正则表达式不支持在字符串中多次重复匹配,所以bash可能不适合这项工作。由于东西都放在自己的线路,虽然,你可以尝试用它来分割事物和模式应用到像每一行:

f=$'\n\tShare1 Disk\n\tShare2 Disk\n\tPrnt1 Printer' 
regex=$'\t(\S+?)\\s+Disk' 
while IFS=$'\n' read -r line; do 
    if [[ $line =~ $regex ]] 
    then 
     printf 'New match: %s\n' "${BASH_REMATCH[@]:1}" 
    else 
     echo "No matches" 
    fi 
done <<<"$f"