有没有一种“规范”的方法?我一直在使用head-n|tail-1来完成这个任务,但我一直在想是否有一个Bash工具专门从文件中提取一行(或一系列行)。

我所说的“规范”是指一个主要功能就是这样做的程序。


当前回答

大文件的最快解决方案始终是尾部|头部,前提是两个距离:

从文件开头到开始行。我们称之为S从最后一行到文件结尾的距离。是E吗

是已知的。然后,我们可以使用这个:

mycount="$E"; (( E > S )) && mycount="+$S"
howmany="$(( endline - startline + 1 ))"
tail -n "$mycount"| head -n "$howmany"

多少只是所需的行数。

更多详情请参见https://unix.stackexchange.com/a/216614/79743

其他回答

您也可以使用sed打印并退出:

sed -n '10{p;q;}' file   # print line 10

如果有多行由\n分隔(通常为新行)。您也可以使用“cut”:

echo "$data" | cut -f2 -d$'\n'

您将从文件中获得第二行-f3给你第三行。

UPDATE 1:在awk中找到了更快的方法

仅需5.353秒即可获得133.6 mn以上的行:

行号='133668997';(时间(pvE0<~/master_primelist_18a.txt|LC_ALL=C mawk2-F'^$'-v\_=“${rownum}”--'_{exit}!--_'))

in0: 5.45GiB 0:00:05 [1.02GiB/s] [1.02GiB/s] [======> ] 71%            
     ( pvE 0.1 in0 < ~/master_primelist_18a.txt | 
     LC_ALL=C mawk2 -F'^$' -v  -- ; )  5.01s user 

1.21s系统116%cpu 5.353总计

77.37219=195591955519519519559551=0x296B0FA7D668C4A64F7F=

===============================================

我想质疑perl比awk更快的观点:

因此,虽然我的测试文件的行数没有那么多,但它的大小也是原来的两倍,为7.58GB-

我甚至给了perl一些内置的优势——比如行号中的硬编码,并且还排在第二位,从而从OS缓存机制中获得了任何潜在的加速(如果有的话)

 f="$( grealpath -ePq  ~/master_primelist_18a.txt )"
 rownum='133668997'
 fg;fg; pv < "${f}" | gwc -lcm 
 echo; sleep 2; 
 echo; 
 ( time ( pv -i 0.1 -cN in0 < "${f}" | 
        
    LC_ALL=C mawk2 '_{exit}_=NR==+__' FS='^$' __="${rownum}" 

 ) ) | mawk 'BEGIN { print } END { print _ } NR' 
 sleep 2
 ( time ( pv -i 0.1 -cN in0 < "${f}" | 

    LC_ALL=C perl -wnl -e '$.== 133668997 && print && exit;' 

 ) ) | mawk 'BEGIN { print }  END { print _ } NR' ;

fg: no current job
fg: no current job
7.58GiB 0:00:28 [ 275MiB/s] [============>] 100%
        
148,110,134 8,134,435,629 8,134,435,629   <<<< rows, chars, and bytes 
                                               count as reported by gnu-wc



      in0: 5.45GiB 0:00:07 [ 701MiB/s] [=> ] 71%            
( pv -i 0.1 -cN in0 < "${f}" | LC_ALL=C mawk2 '_{exit}_=NR==+__' FS='^$' ; )  
   6.22s user 2.56s system 110% cpu 7.966 total
   77.37219=195591955519519519559551=0x296B0FA7D668C4A64F7F=


      in0: 5.45GiB 0:00:17 [ 328MiB/s] [=> ] 71%            
( pv -i 0.1 -cN in0 < "${f}" | LC_ALL=C perl -wnl -e ; )  
   14.22s user 3.31s system 103% cpu 17.014 total
   77.37219=195591955519519519559551=0x296B0FA7D668C4A64F7F=

我可以用perl5.36甚至perl-6重新运行测试,如果你认为这会有所不同(也没有安装)

7.966秒(mawk2)与17.014秒(perl 5.34)

在这两者之间,后者是前者的两倍多,显然哪一种在ASCII文件中获取单行数据确实更快。

This is perl 5, version 34, subversion 0 (v5.34.0) built for darwin-thread-multi-2level

Copyright 1987-2021, Larry Wall


mawk 1.9.9.6, 21 Aug 2016, Copyright Michael D. Brennan

获取第n行(单行)

如果您想要一些以后可以自定义而不必处理bash的东西,可以编译这个c程序,并将二进制文件放到您的自定义二进制文件目录中。这假设您知道如何编辑.bashrc文件相应地(仅当您想要编辑路径变量时),如果您不知道,这是一个有用的链接。

要运行此代码,请使用(假设您将二进制代码命名为“行”)。

line [target line] [target file]

实例

line 2 somefile.txt

代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char* argv[]){

  if(argc != 3){
      fprintf(stderr, "line needs a line number and a file name");
      exit(0);     
  }

  int lineNumber = atoi(argv[1]); 
  int counter = 0; 
  char *fileName = argv[2];

  FILE *fileReader = fopen(fileName, "r");
  if(fileReader == NULL){
      fprintf(stderr, "Failed to open file"); 
      exit(0); 
  }

  size_t lineSize = 0;
  char* line = NULL;

  while(counter < lineNumber){
     getline(&line, &linesize, fileReader);
     counter++
  }

  getline(&line, &lineSize, fileReader);

  printf("%s\n", line);     

  fclose(fileReader); 
  return 0; 
}

EDIT:删除fseek并用while循环替换它

保存两次按键,不使用括号打印第N行:

sed  -n  Np  <fileName>
      ^   ^
       \   \___ 'p' for printing
        \______ '-n' for not printing by default 

例如,要打印第100行:

sed -n 100p foo.txt