如何将文件拆分为由关键字

时间:2015-05-07 04:30:30

标签: bash

假设我有一个大文本文件,例如:

variableStep chrom=chr1
sometext1
sometext1
sometext1
variableStep chrom=chr2
sometext2
variableStep chrom=chr3
sometext3
sometext3
sometext3
sometext3

我想将此文件拆分为3个文件: 文件1具有内容

sometext1
sometext1
sometext2

文件2具有内容

sometext2

和文件3具有内容

sometext3
sometext3
sometext3
sometext3

请注意,没有一个" sometext1" " sometext2" " sometext3"将有" variableStep"。

我可以在python中执行此操作,只需遍历行并打开一个新的文件句柄,并在每次遇到" variableStep"时将后续行写入其中。但是,在行的开头,我想知道是否可以在命令行上完成。 请注意,真实文件很大(多个Gbs,因此一次性读取所有内容将不可行)。

由于

2 个答案:

答案 0 :(得分:4)

这将创建具有所需内容的file1file2等:

awk '/variableStep/{close(f); f="file" ++c;next} {print>f;}' file

如何运作

  • /variableStep/{close(f); f="file" ++c;next}

    每当我们到达包含variableStep的行时,我们会关闭最后使用的文件,为f分配要使用的下一个文件的名称,然后跳过其余的命令并跳转到下一行。

    c是一个计数器,告诉我们当前文件的编号。每次创建新文件名时,它都会增加++

  • print>f

    对于所有其他行,我们将它们打印到根据变量f的值命名的文件。

由于这会逐行处理文件,因此它甚至适用于大量文件。

第一个输出文件如下:

$ cat file1
sometext1
sometext1
sometext1

答案 1 :(得分:3)

您没有要求awkperl解决方案,而是标记了您的问题bash。所以这里。

while read line; do
  if [[ $line =~ ^variableStep ]]; then
    outputfile="file-${line#chr}.txt"
    continue
  fi
  if [ -n "$outputfile" ]; then
    echo "$line" >> "$outputfile"
  fi
done < inputfile.txt

这会跳过文件开头的行,直到遇到包含用于确定输出文件名的模式的行。它假设您chrom=chrN想要将输出存储在file-N.txt中。盐味。

与John的awk解决方案一样,它通过管道逐行处理数据,因此您提供的文件大小并不重要。您甚至可以使用这些解决方案中的任何一个来处理生成此数据的内容,但是如果您这样做,则可能需要调整awk解决方案以在写入后关闭其输出文件。

如果保持一致的文件编号并不重要,可以稍微简化一下。例如:

n=0
while read line; do
  case "$line" in
    variableStep*) ((n++)); continue ;;
  esac
  echo "$line" >> file-${n}.txt
done < inputfile.txt

在此示例中,我们使用case语句模式匹配而不是if语句中的正则表达式来评估行的内容。通常,模式匹配比正则表达式匹配更快。如果对您很重要,您应该对您的实际数据进行测试。