首页 > 解决方案 > grep 获取流中一行中的前 X 个字符

问题描述

抱歉,如果这只是简单的正则表达式,我正在尝试查找一行中的前 X 个字符。我最初的想法是

#!/usr/bin/env bash
X=$1    
cat filename | ... stream ... | grep -r '\w{0,$X}'

虽然我实际上并不认为这会起作用......

基本上,假设我有以下内容:

ATGGCGAGAGAGGTGCCTATAGAGAAATTGAGAAACATAGGTATAGTTGCTCACATTGACGCGGGTAAAACTACGACTAC
CGAGAG**A**ATTCTCTATTACACGGGTAAGACTTACAAGATAGGTGAAGTTCACGAAGGTGCTGCAACGATGGACTGGATGC
CCCAGGAAAAGGAAAGAGGTATAACCATAACCGTTGCAACGACCGCATGTTATTGGACGAGAAACGGGGAGAGGTATCAA

如果我想 grep 到第 2 行的第 7 位,我该怎么做?什么正则表达式只能得到以下内容:

ATGGCGAGAGAGGTGCCTATAGAGAAATTGAGAAACATAGGTATAGTTGCTCACATTGACGCGGGTAAAACTACGACTAC

CGAGAGA

更详细的解释:

我目前拥有的内容打印出指示位置所在的行,以及它之前的行,但不指示输出位置的确切位置(我将我的 fasta 文件放入此):

#!/usr/bin/env bash
spot=$1
myvar=`expr $spot / 81`
#later, I awk in the line number as a column, to navigate
X=$(($spot % 81))
#since each line in the file I'm looking at has 81 characters per line (not including the newline character), this gives the spot I'm looking for

grep -v '>' | awk | 'BEGIN{t=-1}{t = t + 1; {print t, $0}}' | grep -B 1 "$myvar" | head

基本上是尝试创建一个简单的命令行 FASTA 文件导航器(核苷酸序列、蛋白质序列),以及在指定位置查看序列的内容(我这里还没有使用 $X)。

例如,如果我想阅读以下序列中的第 9 位(此处为粗体 T)(所以可能像 10051 位置,它位于第 7 位的第 124 行,

\>NC_000918.1 Aquifex aeolicus VF5, complete sequence

...

ATGGCGAGAGAGGTGCCTATAGAGAAATTGAGAAACATAGGTATAGTTGCTCACATTGACGCGGGTAAAACTACGACTAC
CGAGAG**A**ATTCTCTATTACACGGGTAAGACTTACAAGATAGGTGAAGTTCACGAAGGTGCTGCAACGATGGACTGGATGC
CCCAGGAAAAGGAAAGAGGTATAACCATAACCGTTGCAACGACCGCATGTTATTGGACGAGAAACGGGGAGAGGTATCAA

我希望我的阅读包括一行和“当前”行直到第 9 位,所以(基于我目前拥有的脚本),我想要类似的东西

ATGGCGAGAGAGGTGCCTATAGAGAAATTGAGAAACATAGGTATAGTTGCTCACATTGACGCGGGTAAAACTACGACTAC

CGAGAGA

目前脚本给出(这 123 个 ATGGCG... 列,以防它包装它并使其不清楚)

123    ATGGCGAGAGAGGTGCCTATAGAGAAATTGAGAAACATAGGTATAGTTGCTCACATTGACGCGGGTAAAACTACGACTAC

124    CGAGAGAATTCTCTATTACACGGGTAAGACTTACAAGATAGGTGAAGTTCACGAAGGTGCTGCAACGATGGACTGGATGC

以及其他包含 123、124 的行。我不介意行号(尽管我猜它们很容易摆脱),我只想在这里获得更具体的观点。

我对 bash 脚本还很陌生,所以如果我也写了任何奇怪的东西,请告诉我!

(注意:我显示的行实际上是 VF5 fasta 文件中的前三行,我只是假装让它们成为第 124、123 行等以说明这一点)

标签: bashgrep

解决方案


假设:

  • 您要打印包含指定位置的行,即从序列开头计算的字符长度。
  • 您希望在指定位置终止该行,而不是打印整个匹配的行。
  • 你想包括上一行。

那么请您尝试一下awk解决方案:

#!/bin/bash

spot=$1                         # assigned to "10051" or whatever
awk -v spot="$spot" '!/^>/ {
    amount += length
    if (amount >= spot) {
        print(prev substr($0, 1, spot - (amount - length)))
        exit
    }
    prev = $0 RS
}' file.fasta
  • -v spot="$spot"选项将 awk 变量分配spot给 bash 变量$spot
  • 该模式!/^>/跳过标题行。
  • 变量amount累加字符长度。
  • 变量prev保留前一行(附加 RS,记录分隔符)。

请注意 FASTA 格式的行长不固定为特定值,例如 80。文档仅描述为:

建议所有文本行的长度都短于 80 个字符。

那么最好简单地计算行的长度。


推荐阅读