使用 sed 捕获组

使用 sed 捕获组

我有一个看起来像这样的文件:

chr1    3143567 3143568 .3-2704 1.000000|ENSMUSG00000102693.2
chr1    3143599 3143600 .3-2705 1.000000|ENSMUSG00000102693.2
chr1    3143631 3143632 .3-2706 1.000000|ENSMUSG00000102693.2
chr1    3143663 3143664 .3-2707 1.000000|ENSMUSG00000102693.2
chr1    3143695 3143696 .3-2708 1.000000|ENSMUSG00000102693.2
chr1    3143727 3143728 .3-2709 1.000000|ENSMUSG00000102693.2

我正在编写 2 个 sed 表达式来过滤|第一个表达式之前的所有内容,并且对于结果文件,我会丢弃之后的所有内容,如下.所示:

sed -n -e 's/^.*|//p' original_file.txt > first_result.txt

sed -n -e 's/\..*//p' first_result.txt > final_result.txt

我怎样才能将所有这些写在一行中?

最终目标是捕获ENSMUSG00000102693

答案1

您的命令将丢弃不包含|字符的行以及鼠标基因标识符没有版本号的行。我不确定这是有意的,但这是sed -n与命令p上的标志一起使用的副作用s。我假设这是无意的。

只需使用两个表达式sed

sed -e 's/.*|//' -e 's/\..*//' file >newfile

使用grep具有非标准-o选项的命令,并假设您只想从文件中提取所有 Ensembl 小鼠基因稳定 ID(并且该文件仅包含您想要提取的稳定 ID),

grep -o 'ENSMUSG[[:digit:]]*' file >newfile

您还可以使用两个链接cut命令,每个命令都会对数据进行与sed本答案前面的两个替换类似的修改。使用静态剪切可能比使用正则表达式更快,但我怀疑除非您的输入数据很大,否则您不会看到任何重大的速度差异。

cut -d '|' -f 2 file | cut -d '.' -f 1 >newfile

答案2

您可以使用 GNU grep(看起来比 GNU 的性能稍好一些sed):

$ grep -Po '(?<=\|)[^|.]+' first_result.txt 
ENSMUSG00000102693
ENSMUSG00000102693
ENSMUSG00000102693
ENSMUSG00000102693
ENSMUSG00000102693
ENSMUSG00000102693

  • 该模式的(?<=\|)[^|.]+意思是“查找从首字母( ) 开始(并排除)的所有不是 a|.( ) 的字符”。[^|.]+|(?<=\|)

sed

$ sed 's/.*|\([^|]\+\)\..*/\1/' first_result.txt  
ENSMUSG00000102693
ENSMUSG00000102693
ENSMUSG00000102693
ENSMUSG00000102693
ENSMUSG00000102693
ENSMUSG00000102693
  • 该模式的意思是“删除和( , ).*|\([^|]\+\)\..*之间的所有字符并捕获 ( ) 之间的内容,最后用捕获的模式 ( ) 替换所有字符。|..*|\..*\([^|]\+\)/\1/

或者更简洁地说:

$ sed -E 's/.*\|([^|]+)\..*/\1/'

答案3

您可以使用如下所示的单个sed表达式。将所有内容匹配到最后一个|以忽略,然后捕获最后一个之前的部分.并将其排除在结果中。在任何支持 POSIX BRE 的 sed 上

sed 's/.*|\([^.]*\)\..*/\1/'

如果首选 awk,

awk -F'[|.]' '{ print $(NF-1) }'

相关内容