unix:在文件中获取 10 到 80 个字符

gug*_*ugy 4 awk text-processing wc

我有一个包含行分隔文本的文件:

GCAACACGGTGGGAGCACGTCAACAAGGAGTAATTCTTCAAGACCGTTCCAAAAACAGCATGCAAGAGCG
GTCGAGCCTAGTCCATCAGCAAATGCCGTTTCCAGCAATGCAAAGAGAACGGGAAGGTATCAGTTCACCG
GTGACTGCCATTACTGTGGACAAAAAGGGCACATGAAGAGAGACTGTGACAAGCTAAAGGCAGATGTAGC
Run Code Online (Sandbox Code Playgroud)

由此,我想提取 10 到 80 个字符,因此:

TGGGAGCACGTCAACAAGGAGTAATTCTTCAAGACCGTTCCAAAAACAGCATGCAAGAGCG
GTCGAGCCT
Run Code Online (Sandbox Code Playgroud)

我找到了如何计算文件中的字符数:

  wc -m file
Run Code Online (Sandbox Code Playgroud)

以及如何获取每行的字符数:

 awk '{print substr($0,2,6)}' file
Run Code Online (Sandbox Code Playgroud)

但我找不到让字符 10 到 80 的方法。

换行符不算作字符。

有任何想法吗?

是的,这是来自全基因组的 DNA。我从包含不同支架(在本例中为 10 和 11)的 fasta 文件中提取了这一点 DNA,使用

 awk '/scaffold_10\>/{p=1;next} /scaffold_11/{p=0;exit} p'
Run Code Online (Sandbox Code Playgroud)

最终,我想要一个简单的命令来从指定的脚手架中获取 100 到 800(或类似的)字符。

编辑:问题在这里继续:使用 gff2fasta 而不是 bash 脚本从全基因组中获取部分 DNA 序列

小智 7

$ cat file1
GCAACACGGTGGGAGCACGTCAACAAGGAGTAATTCTTCAAGACCGTTCCAAAAACAGCATGCAAGAGCG
GTCGAGCCTAGTCCATCAGCAAATGCCGTTTCCAGCAATGCAAAGAGAACGGGAAGGTATCAGTTCACCG
GTGACTGCCATTACTGTGGACAAAAAGGGCACATGAAGAGAGACTGTGACAAGCTAAAGGCAGATGTAGC
Run Code Online (Sandbox Code Playgroud)

检查每行的长度

$ awk '{print length,$0}' file1
70 GCAACACGGTGGGAGCACGTCAACAAGGAGTAATTCTTCAAGACCGTTCCAAAAACAGCATGCAAGAGCG
70 GTCGAGCCTAGTCCATCAGCAAATGCCGTTTCCAGCAATGCAAAGAGAACGGGAAGGTATCAGTTCACCG
70 GTGACTGCCATTACTGTGGACAAAAAGGGCACATGAAGAGAGACTGTGACAAGCTAAAGGCAGATGTAGC
Run Code Online (Sandbox Code Playgroud)

打印10-80个字符

$ awk '{print substr($0,10,70)}' RS= file1
TGGGAGCACGTCAACAAGGAGTAATTCTTCAAGACCGTTCCAAAAACAGCATGCAAGAGCG
GTCGAGCC
Run Code Online (Sandbox Code Playgroud)

假设输入不包含空行(RS=启用段落模式,其中每个记录都是一个段落(段落由空行序列分隔))并且它意味着将整个文件加载到内存中。

  • @Kusalananda,不,`RS=` 是_段落模式_。slurp模式见【awk中的Slurp-mode?】(//unix.stackexchange.com/q/304457) (2认同)

hsc*_*hou 6

我想知道应该如何处理文件中的换行符。这算不算一个角色?

如果我们应该从第 10 个字节中取出并打印 71 个字节(A、C、T、G 和换行符),那么 Sato Katsura 解决方案是最快的(这里假设 GNUdd或与 兼容status=none,替换为2> /dev/null(尽管这也会隐藏错误消息,如果有的话) ) 与其他实现):

 dd if=file bs=1 count=71 skip=9 status=none
Run Code Online (Sandbox Code Playgroud)

如果应跳过换行符,则使用以下命令将其过滤掉tr -d '\n'

 tr -d '\n' < file | dd bs=1 count=70 skip=9 status=none
Run Code Online (Sandbox Code Playgroud)

如果应该跳过 Fasta 标头,则为:

 grep -v '^[;>]' file | tr -d '\n' | dd bs=1 count=70 skip=9 status=none
Run Code Online (Sandbox Code Playgroud)

grep -v '^[;>]' file表示跳过所有以;or开头的行>


Sté*_*las 5

对于字节(因此也适用于您的示例中的单字节字符):

dd bs=1 skip=9 count=71 < file 2> /dev/null
Run Code Online (Sandbox Code Playgroud)

或者更有效地使用 GNU dd

dd iflag=fullblock,skip_bytes,count_bytes skip=9 count=71 status=none < file
Run Code Online (Sandbox Code Playgroud)

对于字符,使用zsh

{
  IFS= read -ru0 -k9 discard &&
    IFS= read -ru0 -k71 text &&
    printf %s $text
} < file
Run Code Online (Sandbox Code Playgroud)

(如果文件少于 80 个字符,则不会打印任何内容)。

ksh93bash有一个-N类似于zsh's的选项-k,但它们不支持 NUL 字符,并且bash有问题

使用 GNU awk

awk -v RS='.{1}' -v ORS= 'NR>=10 {print RT}; NR == 80 {exit}'
Run Code Online (Sandbox Code Playgroud)

我们使用.{1}作为.单个字符不会被视为正则表达式。

另一种选择是转换为每个字符具有固定字节数(并且具有所有可能的字符)的字符编码,例如每个字符具有 4 个字节的 UTF-32LE:

< file iconv -t UTF-32LE |
   dd bs=4 skip=9 count=71 2> /dev/null |
   iconv -f UTF-32LE
Run Code Online (Sandbox Code Playgroud)