我的文件夹中有 12,000 个文件,它们具有类似的命名约定,因为我在较大的文件上使用了 csplit。我需要按文件中的第一行对这些文件进行排序,然后连接相似的文件。
每个文件的第一行都以 "> 1"、"> 2"、"> 3" 或 "> 4" 开头,因此我最终需要所有 "> 4" 文件最终成为一个单一的内聚文件(而且我不需要删除这个 > 4 标头)
例子:
文件 xx1 xx3000 和 xx449 看起来像这样
> 4 speciesX1
ATGC
我需要它最终看起来像
> 4 speciesX1
ATGC
> 4 speciesX3000
ATGC
> 4 speciesX449
ATGC
任何人都可以帮助我,因为我尝试用 sed -n -e '/> 4/,/>/ p' big_file >speciesX.txt 分割原始文件,但它没有打印我想要的块。
答案1
awk 'FNR==1 && ! /^> 4/ {nextfile}1' * > speciesX.txt
如果当前文件的第一行不以 开头,这将跳到下一个文件> 4
。所有其他行都打印到标准输出。 stdoutspeciesX.txt
由 shell重定向到。
注意:1
脚本末尾的评估为 true,导致执行 awk 的默认操作(打印当前行)。这是一个常见的awk
习惯用法,因为 awk 脚本本质上是一系列test-condition { action-if-true }
规则,其中测试条件或操作都可以省略。如果没有测试条件,则始终执行该操作,如果没有操作,则print
默认使用。
修改上面的一行以匹配 、 等并在每次运行时重定向到不同的文件是很容易的/^> 1/
,/^> 2/
但是如果您想一次为所有输入文件创建输出文件,只需运行一次脚本,您就可以可以做这样的事情:
awk 'FILENAME ~ /\.out$/ {nextfile};
FNR==1 && ! /^> [0-9]/ {nextfile};
FNR==1 {outfile=$2 ".out"};
{print > outfile}' *.txt
首先,这检查当前输入文件是否以.out
.如果是,则跳到下一个文件。如果您的所有输入文件都以例如结尾,则没有必要,.txt
但我不知道是否是这种情况(您没有说),最好适当处理这种情况。
然后,它检查每个文件的第一行,如果它与可接受的模式不匹配(即“以 开头>
,后跟一个空格,然后是一个数字”),则它会跳到下一个文件。
否则,“.out”将附加到第一行的第二个字段以构造输出文件名。
然后,每行输入都会打印到输出文件名中。您最终会得到文件、、、1.out
等。您可以稍后使用 重命名它们。2.out
3.out
4.out
mv
请注意, awk 中的>
和>>
重定向工作方式与 shell 中的工作方式略有不同:
- Shell 将删除并覆盖现有文件每次
>
使用时(您必须使用>>
附加到文件)。 - awk 将删除并覆盖文件只有第一次它看到该文件名在脚本的单次运行内,所有后续输出都会附加到同一文件名(在同一脚本运行中)。
>>
即使脚本第一次看到文件名,也可以防止擦除和覆盖,即它总是会附加。
顺便说一句,脚本的最后一行{print > outfile}
是 awk 规则的示例,其中有一个没有测试条件的操作。这对每个输入行执行(除非先前规则的操作类似于next
或nextfile
立即跳到下一行或下一个文件)。
答案2
尝试这个:
IFS=$'\n' i=1; for header in $(egrep -m1 '> [0-9]' * -oh | sort | uniq); do grep -rl "$header" . | xargs -I{} cat {} >> file${i}; ((i++)); done
在包含 12000 个文件的目录中运行此命令,之后您将拥有名为 file1、file2、file3 等的单独文件,每个文件包含具有相同标头开头(“> 1”、“> 2”)连接的所有文件一起。
解释:
egrep -m1 '> [0-9]' * -oh | sort | uniq - find all headers starting with "> number" ("> 1", "> 2") and remove duplicates.
IFS=$'\n' i=1; for header in $(...); do ...; done - iterate over the list of headers.
grep -rl "$header" . | xargs -I{} cat {} >> file${i}; ((i++)); - for each header concat all files started by the header to a separate file.