Linux Shell提取匹配模式之间的子字符串

时间:2019-02-05 22:22:22

标签: regex linux bash

假设我有一个字符串poskek|gfgfd|XLSE|a1768|d234|uijjk,而我只想提取LSE部分。

我只知道在LSE之前是|X,在我对|感兴趣的部分之后是LSE

5 个答案:

答案 0 :(得分:3)

使用sed的另一个答案应该可行,但是我总是发现sed对于正则表达式选择有些尴尬,因为它实际上是用于替换的(因此,为什么需要在模式的任何一边两侧带有.*,实际需要的部分需要放在括号中)。这是使用grep的解决方案:

grep -Po '\|X\K[^|]+'

-P发信号通知grep使用Perl的高级正则表达式引擎

-o仅打印行的匹配部分

\|X匹配文字竖线和大写字母X

\K忘记当前已匹配的内容(不要将其包含在最终输出中)

[^|]+除竖线以外的一个或多个字符

答案 1 :(得分:2)

echo 'poskek|gfgfd|XLSE|a1768|d234|uijjk' | sed -n 's/.*|X\([^|]\+\).*/\1/p'

这应该可以解决问题。

解释:

除非指定,否则

sed -n将不会打印任何内容

s/-搜索并替换
.*|X-匹配所有内容,包括|X
\([^|]\+\)-捕获多个(至少一个)不是|的字符
.*-匹配其余文本(只是为了“吃饱”)
/\1/p-用第一个捕获内容替换所有匹配的文本,然后打印

答案 2 :(得分:2)

作为纯bash解决方案,请尝试:

str='poskek|gfgfd|XLSE|a1768|d234|uijjk'
ext=${str#*|X}
ext=${ext%%|*}
echo "$ext"

如果可以使用正则表达式,则也可以进行以下操作:

if [[ $str =~ .*\|X([^|]+) ]]; then
    echo "${BASH_REMATCH[1]}"
fi

答案 3 :(得分:1)

对于这种特殊情况,您可以执行非常规的操作:

awk '$1=="X"{$1="";print}' FS= OFS= RS=\|

答案 4 :(得分:0)

尝试

 echo 'poskek|gfgfd|XLSE|a1768|d234|uijjk' | 
   awk -F "|" '{for(i=1;i<=NF;++i) printf "%s", (substr($i,1,1)=="X"?substr($i,2):"")}'

其中

-F是字段分隔符 => '|'   NF是字段数