当前位置: 首页>>技术教程>>正文


如何删除文件中少于 6 个字符的所有行?

,

问题描述

我有一个包含大约 1000 万行的文件。

我想删除文件中少于六个字符的所有行。

我该怎么做呢?

最佳答案

有很多方法可以做到这一点。

使用 grep

grep -E '^.{6,}$' file.txt >out.txt

现在,out.txt 将包含具有六个或更多字符的行。

反转方式:

grep -vE '^.{,5}$' file.txt >out.txt

使用 sed ,删除长度为 5 或更少的行:

sed -r '/^.{,5}$/d' file.txt

反向方式,打印长度为六行或更多的行:

sed -nr '/^.{6,}$/p' file.txt 

您可以使用 > 运算符(如 grep)将输出保存在不同的文件中,或者使用 sed-i 选项就地编辑文件:

sed -ri.bak '/^.{6,}$/' file.txt 

原始文件将备份为 file.txt.bak ,修改后的文件将备份为 file.txt

如果您不想保留备份:

sed -ri '/^.{6,}$/' file.txt

使用 shell,速度较慢,不要这样做,这只是为了展示另一种方法:

while IFS= read -r line; do [ "${#line}" -ge 6 ] && echo "$line"; done <file.txt

使用 python ,甚至比 grepsed 慢:

#!/usr/bin/env python2
with open('file.txt') as f:
    for line in f:
        if len(line.rstrip('\n')) >= 6:
            print line.rstrip('\n')

最好使用列表理解来变得更加Pythonic:

#!/usr/bin/env python2
with open('file.txt') as f:
     strip = str.rstrip
     print '\n'.join([line for line in f if len(strip(line, '\n')) >= 6]).rstrip('\n')

次佳答案

这很简单:

grep ...... inputfile > resultfile   #There are 6 dots

这是非常有效的,因为 grep 不会尝试解析超出其需要的内容,也不会以任何方式解释字符:它只是在看到后立即将(整)行发送到 stdout(然后 shell 将其重定向到结果文件)该行有 6 个字符(正则表达式上下文中的 . 与任意 1 个字符匹配)。

因此 grep 只会输出具有 6 个(或更多)字符的行,而其他行不会被 grep 输出,因此它们不会进入结果文件。

第三种答案

解决方案#1:使用 C

最快的方法:编译并运行这个C程序:

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

#define MAX_BUFFER_SIZE 1000000

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

    if(argc == 3)
        length = atoi(argv[2]);
    else
        return 1;

    FILE *file = fopen(argv[1], "r");

    if(file != NULL) {
        char line[MAX_BUFFER_SIZE];

        while(fgets(line, sizeof line, file) != NULL) {
            char *pos;

            if((pos = strchr(line, '\n')) != NULL)
                *pos = '\0';
            if(strlen(line) >= length)
                printf("%s\n", line);
        }

        fclose(file);
    }
    else {
        perror(argv[1]);
        return 1;
    }
    
    return 0;
}

使用 gcc program.c -o program 编译,使用 ./program file line_length 运行(其中 file = 文件路径,line_length = 最小行长度,在您的情况下为 6 ;最大行长度限制为每行 1000000 个字符;您可以通过更改 MAX_BUFFER_SIZE 的值来更改此设置) 。

(用 \\0 替换 \\n 的技巧发现了 here 。)

与除 shell 解决方案之外针对此问题提出的所有其他解决方案进行比较(在约 91MB 文件上测试,该文件有 10M 行,平均长度为 8 个字符):

time ./foo file 6

real    0m1.592s
user    0m0.712s
sys 0m0.160s

time grep ...... file

real    0m1.945s
user    0m0.912s
sys 0m0.176s

time grep -E '^.{6,}$'

real    0m2.178s
user    0m1.124s
sys 0m0.152s

time awk 'length>=6' file

real    0m2.261s
user    0m1.228s
sys 0m0.160s

time perl -lne 'length>=6&&print' file

real    0m4.252s
user    0m3.220s
sys 0m0.164s

sed -r '/^.{,5}$/d' file >out

real    0m7.947s
user    0m7.064s
sys 0m0.120s

./script.py >out
real    0m8.154s
user    0m7.184s
sys 0m0.164s

解决方案#2:使用 AWK:

awk 'length>=6' file
  • length>=6 :如果 length>=6 返回 TRUE,则打印当前记录。


解决方案 #3:使用 Perl:

perl -lne 'length>=6&&print' file
  • 如果 lenght>=6 返回 TRUE,则打印当前记录。


% cat file
a
bb
ccc
dddd
eeeee
ffffff
ggggggg
% ./foo file 6
ffffff
ggggggg
% awk 'length>=6' file   
ffffff
ggggggg
% perl -lne 'length>=6&&print' file
ffffff
ggggggg

第四种答案

您可以在 Ex 模式下使用 Vim:

ex -sc 'v/\v.{6}/d' -cx file
  1. \\v 开启魔法

  2. .{6} 查找包含 6 个或更多字符的行

  3. v 反转选择

  4. d删除

  5. x 保存并关闭

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/13793.html,未经允许,请勿转载。