【问题标题】:Remove Last Character of Each Line that Starts With @删除以@开头的每一行的最后一个字符
【发布时间】:2016-11-06 15:46:51
【问题描述】:

我想从我的 300 多个文件中删除以 @ 开头的每一行的最后一个字符,每个文件大约 1gb。

我的示例文件如下:

@1_1101_1473_2134_1
CATGCGGGAGGAGGAGGACGAGGACCTGCTGCAGTTTGCCATCCAGCAGAGTCTCCTGGAGGTGGGGGCCGAGTACGACCAGGTAACACCCC
+
FFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFBBFFFFF<FFFFFF/BFBF7FFBFFFFFFFFFFBFFFFFF
@1_1101_1635_2243_1
CATGCACACCTCCCGGTCTCCGTTGTGGAGGATCAGGTCCACGATCTCCTGGGTCCACGTGGTGCCTACACACACACACACACACACACACA
+
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

我想从以 @ 开头的行中删除最后一个字符 1,所以我的输出应该是

@1_1101_1473_2134_
CATGCGGGAGGAGGAGGACGAGGACCTGCTGCAGTTTGCCATCCAGCAGAGTCTCCTGGAGGTGGGGGCCGAGTACGACCAGGTAACACCCC
+
FFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFBBFFFFF<FFFFFF/BFBF7FFBFFFFFFFFFFBFFFFFF
@1_1101_1635_2243_
CATGCACACCTCCCGGTCTCCGTTGTGGAGGATCAGGTCCACGATCTCCTGGGTCCACGTGGTGCCTACACACACACACACACACACACACA
+
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

我首先尝试了python,它适用于这些行,但作为一个新手,我无法弄清楚如何在输出中保留所有行。

with open("file.fq") as f:
        for line in f:
                length=(len(line)-2)
                if line.startswith('@'):
                        line=line[:length]+''+line[length+1:]
                        print(line)

这当然只给出“线条”,但我想证明它有效

@1_1101_1473_2134_

@1_1101_1635_2243_

然后我尝试了 awk 和 sed。我可以使用 awk 选择以 @ 开头的行,如下所示:

awk '{if (/^@/)}'

我可以使用 sed 删除每行的最后一个字符:

sed {'s/.$//'}

所以我当然尝试将这两者结合起来,就像:

awk '{if (/^@/)}' | sed {'s/.$//'} file.fq

这不起作用。

顺便说一句,如果可能的话,我宁愿直接从我的文件中删除这些字符,而不是创建一个删除这些字符的新文件,因为我有超过 300gb 的数据,当然我更喜欢一种快速的方法。

高度赞赏任何升级我的命令的帮助,或以任何其他方式执行此操作的任何替代方式。此外,我希望在循环中为所有文件运行正确的命令,这就是为什么我首先尝试生成一个 python 脚本,所以任何关于你的解决方案的循环阶段的帮助也会很棒。

非常感谢

【问题讨论】:

  • 您在 Python 中的唯一错误是将 print() 缩进成为 if 语句的一部分。 取消缩进该行与for循环中的其余代码处于同一级别。
  • 除非您使用ed,否则您无法在不创建新文件的情况下执行此操作,即使那样您也将使用文件大小的缓冲区,因此不会有任何区别。 sed -i 等都在运行中创建 tmp 文件。
  • 如果某个答案解决了您的问题,请通过单击旁边的大复选标记 (✓) 接受它,并可选择对其进行投票(投票至少需要 15 个声望点)。如果您发现其他答案有帮助,请给他们投票。接受和投票有助于未来的读者。请参阅the relevant help-center article。如果您的问题尚未完全得到解答,请提供反馈。如果您认为自己找到了最佳解决方案,请将其发布为答案并自我接受。

标签: python bash awk sed


【解决方案1】:
$ sed -i '/^@/ s/.$//' file.fq
$ cat file.fq
@1_1101_1473_2134_
CATGCGGGAGGAGGAGGACGAGGACCTGCTGCAGTTTGCCATCCAGCAGAGTCTCCTGGAGGTGGGGGCCGAGTACGACCAGGTAACACCCC
+
FFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFBBFFFFF<FFFFFF/BFBF7FFBFFFFFFFFFFBFFFFFF
@1_1101_1635_2243_
CATGCACACCTCCCGGTCTCCGTTGTGGAGGATCAGGTCCACGATCTCCTGGGTCCACGTGGTGCCTACACACACACACACACACACACACA
+
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
  • /^@/ 匹配以 @ 开头的行
  • s/.$//删除这些行的最后一个字符
  • -i 就地编辑,-i 选项的用法因sed 版本而异,请参阅语法文档


python

import fileinput

with fileinput.input(inplace=True) as f:
    for line in f:
        line = line.rstrip('\n');

        if line.startswith('@'):
            line = line[:-1]

        print(line)
  • 这将接受文件作为命令行参数,因此您可以执行./del_last.py *.fq 之类的操作
  • 另见Python's slice notation

【讨论】:

  • 惊人的一个班轮!非常感谢!我是如此接近! :D 我确实尝试让 sed 找到行或 awk 删除字符但不能(((因此,如果有人来到这篇文章并希望将其作为许多文件的循环,您可以在命令行上执行让我们说目录中的所有文件在末尾使用通配符而不是文件名,如 (( sed -i '/^@/ s/.$//' * )) 干杯
【解决方案2】:

对于您的 Python 脚本,您只需将 print 语句从条件套件中取出:

with open("file.fq") as f:
    for line in f:
        if line.startswith('@'):
            line = line[:-2] + '\n'
        print(line, end = '')

如果您有足够的内存保存一个完整的文件和一个副本,您可以使用正则表达式并立即对整个文件进行更改。

import re
pattern = '^(@.*?)\S\r?\n'
rex = re.compile(pattern, flags = re.MULTILINE)
with open("file.fq") as f:
    data = f.read()
new = rex.sub(r'\1\n', data)

【讨论】:

  • 你不需要先去掉换行符吗?
  • @Sundeep - 如果 OP 只关心打印以实现所需的输出格式,那么,是的,需要考虑打印语句换行 - 请参阅编辑。如果你去掉空格然后写回一个文件,你会失去一些结构。
  • 据我所知并进行了测试,如果line 的换行符没有先被删除,line[:-1] 将删除换行符 :)
  • @Sundeep - 你是对的,我的错。除非你想投反对票,否则我会删除它。
  • 我建议只编辑相关细节:)
【解决方案3】:

这应该可行:

sed 's/\(^@.*\)./\1/' <file>

【讨论】:

  • 您的模式不需要$ 来指示行尾。
【解决方案4】:

从第一个 @ 到下一个 @。他们的行号是否相等?整个文件是 4 吗?

@1_1101_1473_2134_1
CATGCGGGAGGAGGAGGACGAGGACCTGCTGCAGTTTGCCATCCAGCAGAGTCTCCTGGAGGTGGGGGCCGAGTACGACCAGGTAACACCCC
+
FFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFBBFFFFF<FFFFFF/BFBF7FFBFFFFFFFFFFBFFFFFF
@1_1101_1635_2243_1
CATGCACACCTCCCGGTCTCCGTTGTGGAGGATCAGGTCCACGATCTCCTGGGTCCACGTGGTGCCTACACACACACACACACACACACACA
+
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

如果是这样的话。它可能对你有帮助。查找第一个 @ 然后删除第 4 行的最后一个字符。然后从这一行 (4) 找到下一个 @ 然后 +4 行并删除最后一个字符....

【讨论】:

  • 感谢您的评论。 (顺便说一句,我没有投反对票)我也考虑过你的想法,这对我的文件来说是正确的,它们在每 4 行。例如,我可以使用 (( awk '{if (NR%2==0) {$0=$0 "newcharacter"}; print}' file )) 将字符添加到每一行的末尾,但我无法将其制定为删除每个第 4 行的最后一行。谢谢!
猜你喜欢
  • 2015-10-23
  • 2019-03-20
  • 2014-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-08
相关资源
最近更新 更多