2016-01-05 215 views
1

开始我有一系列的条目,可以通过此字符串来表示零个或一个位置:正则表达式:捕捉字符模式从字符串

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的值,无论前面有没有字符?请记住,唯一可以“硬编码”到表达式中的是要匹配的模式。

回答

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 

的“从“模式(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") 
+0

你能解释这个'sed'命令的每个部分在做什么吗? 。 – user5359531

+0

肯定的是,更新的回答更多细节 –

2

这个正则表达式在我的本地测试中工作。请尝试:

^.?[RD] 

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

+0

即返回R/D,以及任何前面的字符。不知何故,我已经完成了这个早期的工作,但是当我改变了其他地方的某些事情时,我的实施失败 – user5359531

+0

这个答案的“编辑”似乎要求比赛结果的前/后处理是不可能的。 :( http://stackoverflow.com/questions/3061162/regex-to-match-a-pattern-and-exclude-a-part-of-the-string – mcsilvio

+0

建立在这个没有工作,作为一种替代解决方案。我我用下面的:| “?^ [RD]”。'回声 “$ my_string的” grep -E -o | grep的-E -o “[RD]”'这样做,第一grep的返回的r '或如前述任一角色沿'D',而第二个grep的回报只是'R'或'单独D'。不优雅,所以我最终没有使用它,但如果'sed'它是有用还是显得太在这一点上,我已经找到了足够的'sed'和更多关于正则表达式来使用它。 – user5359531

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 
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

2

使用修饰符 'G' 用于全球时,这做的:(^|).?(R|D)

参见regex101 here