正则表达式:从字符串的开头捕获字符模式零或一个位置

时间:2016-01-05 02:23:25

标签: regex bash

我有一系列条目,可以用这个字符串表示:

my_string="-D-K4_NNNN_M116_R1_001.gz _D-K4_NNNN_M56_R1_001.gz R-K4_NNNN_KQ9_R1_001.gz D-K4_NNNN_M987_R1_001.gz _R-K4_NNNN_M987_R1_001.gz"

对于每个条目,我需要返回它是以“R”还是“D”开头。为了做到这一点,我需要忽略它之前的任何角色。所以,我写了这个正则表达式:

for i in $my_string; do echo $i | grep -E -o "^*?[RD]"; done

但是,对于没有字符开头的条目,这只会返回RD

如何让这个正则表达式在每种情况下返回RD值,无论前面是否有字符?请记住,表达式中唯一可以“硬编码”的是要匹配的模式。

5 个答案:

答案 0 :(得分:3)

使用参数扩展在使用grep之前删除前缀:

for i in $my_string; do echo ${i#[^RD]} | grep -o "^[RD]" ; done

或使用没有grep的简单测试(因为你已经知道每个项目都以R或D开头):

for i in $my_string; do
    if [[ $i =~ ^[^D]?R ]] ; then
       echo 'R'
    else
       echo 'D'
    fi
done

答案 1 :(得分:3)

使用sed

会很容易
sed -r 's/^.?([RD]).*$/\1/'

for i in $my_string; do echo $i | sed -r 's/^.?([RD]).*$/\1/'; done

更新:

以下是命令的每个部分的含义:

-r : extended regular expression, although I think -e should work but
     turns out that during my testing, in order to use capturing group
     in regex, I need -r.  Anyway, not the main point

该脚本可以读作:

s/XXXX/YYYY/  : substitude from XXXX to YYYY

"来自" pattern(XXXX)表示:

^    : start with
.?   : zero or one occurence of any character
(    : start of group
[RD] : either R or D
)    : end of group (which means, the group will contains either R or D
.*   : any number of any character
$    : till the end
"到"模式(YYYY):

\1   : content of capture group 1 in the "from" pattern (which is the "R or D")

答案 2 :(得分:2)

这个正则表达式在我的本地测试中起作用。请试一试:

^.?[RD]

我无法想出一种只返回你想要的信的方法。我之后有一个命令来检测返回的字符串是否长于1个字符,如果是,我只返回第二个字符。

答案 3 :(得分:2)

我不是100%肯定你在问什么(我知道你想在文件名的开头只匹配R和D,不管它之前的字符,如果有的话),但我认为你应该使用lookbehind,在php中你会做

$re = "/(?<=^\S|\s\S|\s)[RD]/"; 
$str = "-D-K4_NNNN_M116_R1_001.gz _D-K4_NNNN_M56_R1_001.gz R-K4_NNNN_KQ9_R1_001.gz D-K4_NNNN_M987_R1_001.gz _R-K4_NNNN_M987_R1_001.gz"; 

preg_match_all($re, $str, $matches);

您可以看到输出here

要在bash中使用Perl语法,您必须启用它。 https://unix.stackexchange.com/questions/84477/forcing-bash-to-use-perl-regex-engine

如果您需要https://regex101.com/r/vV3nS3/1

,可以在此处测试正则表达式

答案 4 :(得分:2)

当使用修饰符'g'表示全局:(^| ).?(R|D)

时,会这样做

请参阅regex101 here