【问题标题】:Multiple replacements on first line of a very large file在一个非常大的文件的第一行进行多次替换
【发布时间】:2012-11-25 19:36:57
【问题描述】:

我有一个大文件,第一行是:

CHR开始末端链ref_context repeat_masked s1_smpl_context s1_c_count s1_ct_count s1_non_ct_count s1_m%s1_score s1_snp s1_indels s2_smpl_context s2_c_count s2_ct_count s2_non_ct_count s2_m%s2_score s2_snp s2_indels s3_smpl_context s3_c_count s3_ct_count s3_non_ct_count s3_m%s3_score s3_snp s3_indels ... P>

高达 s8。

我想将所有s1s4 的实例替换为L1L4,然后将s5s8 的所有实例替换为W1W4。 最好使用grepawk 或其他方式来执行此操作?

【问题讨论】:

  • 文件到底有多大?
  • 文件有3000万行

标签: linux replace sed awk grep


【解决方案1】:

仅在文件的第一行将s[1-4] 替换为L[1-4] 并将s[5-8] 替换为W[1-4]

sed -Ee '1s/s([1-4])/L\1/g' -e '1s/s([5-8])/W\1/g' -e '1y/5678/1234/' -e '1q' file

演示:

$ 猫文件

CHR开始末端链ref_context repeat_masked s1_smpl_context s1_c_count s1_ct_count s1_non_ct_count s1_m%s1_score s1_snp s1_indels s2_smpl_context s2_c_count s2_ct_count s2_non_ct_count s2_m%s2_score s2_snp s2_indels s3_smpl_context s3_c_count s3_ct_count s3_non_ct_count s3_m%s3_score s3_snp s3_indels s4_Smpl_context s4_c_count s4_ct_count s4_non_ct_count s4_m%s4_score s4_snp s4_indels s5_smpl_context s5_c_count s5_ct_count s5_non_ct_count s5_m %s5_score s5_snp s5_indels s6_smpl_context s6_c_count s6_ct_count s6_non_ct_count s6_m%s6_score s6_snp s6_indels s7_Smpl_context s7_c_count s7_ct_count s7_non_ct_count s7_m%s7_score s7_snp s7_indels s8_smpl_context s8_c_count s8_ct_count s8_non_ct_count s8_m%s8_score s8_snp s8_indels

s1_line_2

s3_line_3

s8_line_4

$ sed -Ee '1s/s([1-4])/L\1/g' -e '1s/s([5-8])/W\1/g' -e '1y/ 5678/1234/' -e '1q' 文件

CHR开始末端链ref_context repeat_masked L1_smpl_context L1_c_count L1_ct_count L1_non_ct_count L1_m%L1_score L1_snp L1_indels L2_smpl_context L2_c_count L2_ct_count L2_non_ct_count L2_m%L2_score L2_snp L2_indels L3_smpl_context L3_c_count L3_ct_count L3_non_ct_count L3_m%L3_score L3_snp L3_indels L4_Smpl_context L4_c_count L4_ct_count L4_non_ct_count L4_m%L4_score L4_snp L4_indels W1_smpl_context W1_c_count W1_ct_count W1_non_ct_count W1_m %W1_score W1_snp W1_indels W2_smpl_context W2_c_count W2_ct_count W2_non_ct_count W2_m%W2_score W2_snp W2_indels W3_Smpl_context W3_c_count W3_ct_count W3_non_ct_count W3_m%W3_score W3_snp W3_indels W4_smpl_context W4_c_count W4_ct_count W4_non_ct_count W4_m%W4_score W4_snp W4_indels

【讨论】:

  • 考虑同时使用-i 参数进行内联替换,这样大文件就不会复制到临时空间中。
  • @nullrevolution。使用-i 会使用临时文件复制文件。它只是防止用户必须自己进行重定向的语法糖,并用于混淆正在发生的事情,诱使人们相信没有使用临时文件。应该避免。
  • 还可以考虑在第二行添加 -e '2q' 以退出 sed。即使不再需要进行任何编辑,上述内容也会读取整个文件(而且文件很大)。
  • @sudo_O sed -Ee '1s/s([1-4])/L\1/g' -e '1s/s([5-8])/W\1/g' -e '1y/5678/1234/' -e '1q' file 返回 -E 作为无效选项
  • 可能减去-r 然后,执行--help 并寻找extended regexp 选项。
【解决方案2】:

由于您的替换都不会更改第一行的长度,因此您还可以选择直接修改原始文件。我不认为你可以用任何常用的 shell 命令来做到这一点,但你可以编写一个程序,例如Python 可以做到这一点。

但是,如果文件太大以至于您无法制作临时副本,我只会考虑此选项。

#!/usr/bin/env python

import os

# On windows, you need to use os.O_RDWR | os.O_BINARY
fd = os.open('modex', os.O_RDWR)
f = os.fdopen(fd)
f.seek(0)
line = f.readline()
replacements = [("s%s" % x, "L%s" % x) for x in range(1,5)] \
        + [("s%s" % (x+4), "W%s" % x) for x in range(1,5)]
for (s,r) in replacements:
    line = line.replace(s, r)
# We cannot use python file objects here, because f.write() _always_ appends,
# regardless of the seek position. So we use the raw object here.
# Mixing raw IO and python IO should be done with care, however we should be
# ok here, as we did not write anything yet.
os.lseek(fd, 0, os.SEEK_SET)
os.write(fd, line)
f.close()

【讨论】:

    猜你喜欢
    • 2015-05-19
    • 2012-11-24
    • 1970-01-01
    • 2017-03-26
    • 2020-07-30
    • 2018-08-05
    • 2015-05-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多