【发布时间】:2019-02-05 22:22:21
【问题描述】:
假设我有一个字符串poskek|gfgfd|XLSE|a1768|d234|uijjk,我只想提取LSE 部分。
我只知道在LSE前面会有|X,在我感兴趣的部分后面直接有|LSE。
【问题讨论】:
-
这是我正在尝试的代码:
echo 'poskek|gfgfd|XLSE|a1768|d234|uijjk' | sed 's/.*|X([^|]\+).*/\1/'
假设我有一个字符串poskek|gfgfd|XLSE|a1768|d234|uijjk,我只想提取LSE 部分。
我只知道在LSE前面会有|X,在我感兴趣的部分后面直接有|LSE。
【问题讨论】:
echo 'poskek|gfgfd|XLSE|a1768|d234|uijjk' | sed 's/.*|X([^|]\+).*/\1/'
使用sed 的另一个答案应该可以,但我总是发现sed 对于正则表达式的选择有点尴尬,因为它实际上是为了替换(因此为什么模式的任何一侧都需要与@987654323 @ 和你真正想要的部分需要放在括号中)。这是使用grep的解决方案:
grep -Po '\|X\K[^|]+'
-P 向grep 发出信号以使用更高级的 Perl 正则表达式引擎
-o 只打印该行的匹配部分
\|X 匹配文字竖线和大写 X
\K忘记当前匹配的内容(不要包含在最终输出中)
[^|]+除竖线以外的一个或多个字符
【讨论】:
echo 'poskek|gfgfd|XLSE|a1768|d234|uijjk' | grep -Po '\|X\K[^|]+',我收到以下错误消息:usage: grep [-abcDEFGHhIiJLlmnOoqRSsUVvwxZ] [-A num] [-B num] [-C[num]] [-e pattern] [-f file] [--binary-files=value] [--color=when] [--context[=num]] [--directories=action] [--label] [--line-buffered] [--null] [pattern] [file ...] –
-P 选项。输入grep --version 会得到什么?
grep (BSD grep) 2.5.1-FreeBSD
作为纯 bash 解决方案,请尝试:
str='poskek|gfgfd|XLSE|a1768|d234|uijjk'
ext=${str#*|X}
ext=${ext%%|*}
echo "$ext"
如果正则表达式可用,以下也可以:
if [[ $str =~ .*\|X([^|]+) ]]; then
echo "${BASH_REMATCH[1]}"
fi
【讨论】:
if [[ $str =~ \|X([^|]+) ]];
echo 'poskek|gfgfd|XLSE|a1768|d234|uijjk' | sed -n 's/.*|X\([^|]\+\).*/\1/p'
这应该可以解决问题。
解释:
sed -n 除非指定,否则不会打印任何内容
s/ - 搜索和替换.*|X - 匹配直到并包括|X的所有内容\([^|]\+\) - 捕获多个(至少一个)不是|的字符.* - 匹配其余文本(只是为了“吃掉它”)/\1/p - 用第一个捕获替换所有匹配的文本,然后打印
【讨论】:
echo 'poskek|gfgfd|XLSE|a1768|d234|uijjk' | sed 's/.*|X([^|]\+).*/\1/'
对于这种特殊情况,您可以做一些非常规的做法:
awk '$1=="X"{$1="";print}' FS= OFS= RS=\|
【讨论】:
试试这个
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 是字段数
【讨论】:
X 开头的组