我有一个关于grep的问题。我正在寻找多行文本中的特定模式。同一条线上经常有多个匹配。我已经解决了如何提取我的模式,但grep将每个匹配放在一个新行上。有没有办法阻止grep这样做?理想情况下,我希望提取所有匹配项并保留原始文件的行结构。
以下是一个例子:
一条输入线(其中有数千条):
MUC3A|ENST00000414964[in] MUC3A|ENST00000422757[in] MUC3A|ENST00000319509[in] MUC3A|ENST00000483133[in] RP11-395B7.2.1|ENST00000420080[me] RP11-395B7.2.1|ENST00000438198[me] RP11-395B7.2.1|ENST00000434775[5g] MUC12|ENST00000536621[5g] MUC12|ENST00000379442[5g] MUC3A|ENST00000480291[5g]
我的grep命令:
grep -oe MUC12[\|A-Za-z0-9-]*\[[A-Za-z0-9]*\]
我目前的输出:
MUC12|ENST00000536621[5g]
MUC12|ENST00000379442[5g]
我理想的输出:
MUC12|ENST00000536621[5g] MUC12|ENST00000379442[5g]
有什么想法吗?我非常感谢任何人都可以提供的见解。
答案 0 :(得分:1)
$ awk '{
s=""
for (i=1;i<=NF;i++) {
if ($i ~ /MUC12[\|A-Za-z0-9-]*\[[A-Za-z0-9]*\]/) {
printf "%s%s",s,$i
s=" "
}
}
print ""
}' file
MUC12|ENST00000536621[5g] MUC12|ENST00000379442[5g]
我会更改你的RE虽然锚定表达式,使用字符类而不是显式范围来简洁和可移植性,并寻找1个或多个字符(+)而不是允许零(*):< / p>
$ awk '{
s=""
for (i=1;i<=NF;i++) {
if ($i ~ /^MUC12\|[[:alnum:]-]+\[[[:alnum:]]+\]$/) {
printf "%s%s",s,$i
s=" "
}
}
print ""
}' file
MUC12|ENST00000536621[5g] MUC12|ENST00000379442[5g]
我也感动了“|”字符列表之外,因为它似乎不属于您发布的示例输入。
答案 1 :(得分:1)
当您设置-o
标记时,grep
将在新行上单独打印每个匹配,并且无法更改此行为。简单的修复包括让grep
打印出每个匹配的行号,然后加入连续编号的行。您可以使用awk
执行此操作。像这样跑:
< file grep -one "MUC12[\|A-Za-z0-9-]*\[[A-Za-z0-9]*\]" | awk -f script.awk
script.awk
的内容:
BEGIN {
FS=":"
}
$1 == y {
sub(/[^:]+:/,"")
r = (r ? r OFS : "") $0
next
}
x {
print x, r
r=""
}
{
x=$0
y=$1
sub(/[^:]+:/,"",x)
}
END {
print x, r
}
或者,这是单行:
< file grep -one "MUC12[\|A-Za-z0-9-]*\[[A-Za-z0-9]*\]" | awk -F ":" '$1 == y { sub(/[^:]+:/,""); r = (r ? r OFS : "") $0; next } x { print x, r; r="" } { x=$0; y=$1; sub(/[^:]+:/,"",x) } END { print x, r }'
此处介绍的方法可以应用于grep
支持的任何正则表达式。与接受的答案不同,这种方法不会因非空白分隔的正则表达式而失败 - 而且可能非常重要。