从多个文件中提取文本行并打印到一个文件

从多个文件中提取文本行并打印到一个文件

我正在开发一个项目,需要将多个文件中的特定数据行整理到一个新的文本文件中。例如,假设我有 3 个文件,每个文件都包含一个值矩阵:

文本文件1

Obs.    TGCP_WM23   STT_WM189   MPO_WM496   PTP_WM724
TGCP_WM23   0.000000    0.174510    0.153292    0.177030
STT_WM189   0.174510    0.000000    0.077663    0.203359
MPO_WM496   0.153292    0.077663    0.000000    0.183706
PTP_WM724   0.177030    0.203359    0.183706    0.000000

文本文件2

Obs.    TGCP_WM15   STT_WM187   MPO_WM485   PTP_WM725
TGCP_WM15   0.000000    0.157164    0.145516    0.168991
STT_WM187   0.157164    0.000000    0.051973    0.187443
MPO_WM485   0.145516    0.051973    0.000000    0.171824
PTP_WM725   0.168991    0.187443    0.171824    0.000000

文本文件3

Obs.    TGCP_WM1    STT_WM184   MPO_WM489   PTP_WM721
TGCP_WM1    0.000000    0.166831    0.161654    0.192732
STT_WM184   0.166831    0.000000    0.059373    0.202718
MPO_WM489   0.161654    0.059373    0.000000    0.185286
PTP_WM721   0.192732    0.202718    0.185286    0.000000

我想自动读取这 3 个文件并将每个文件的第二行打印到一个新文本文件的连续行中,这样新文本文件包含:

新建文本文件

TGCP_WM23   0.000000    0.174510    0.153292    0.177030
TGCP_WM15   0.000000    0.157164    0.145516    0.168991
TGCP_WM1    0.000000    0.166831    0.161654    0.192732

有没有一种相对简单的方法可以使用 Mac 上的终端来执行类似的操作?目前,我正在查看 2,200 个文件,我需要从中提取数据并格式化数据,以便可以运行一些下游分析。我希望避免手动打开所有这些文件,复制文本并粘贴到新文件中,其中值以更有用的方式格式化。

编辑:我正在处理的所有文件都是从名为 Genodive 的程序输出的文本文件。一半的文件是 Fst 矩阵文件,类似于上面显示的示例;其他 1,100 个文件是遗传多样性输出文件,其内容看起来像......


___________________________________________________________________

GenoDive 3.01, 2019-12-12 23:28:01 +0000
Genetic Diversity: Nei 1987.
File: TrkNbr_1083n1282_L1n2_PrelimPops_02SubSampPops_Rep001.txt
8 of 8 individuals included, 6843 of 6843 loci included

– Summary of indices of genetic diversity

Statistic   Value   Std.Dev.    c.i.2.5%    c.i.97.5%   Description
Num 1.418   0.006   1.405   1.428   Number of alleles
Eff_num 1.086   0.002   1.082   1.088   Effective number of alleles
Ho  0.092   0.002   0.089   0.096   Observed Heterozygosity
Hs  0.098   0.002   0.094   0.101   Heterozygosity Within Populations
Ht  0.114   0.002   0.110   0.117   Total Heterozygosity
H't 0.122   0.002   0.117   0.125   Corrected total Heterozygosity
Gis 0.055   0.013   0.030   0.079   Inbreeding coefficient

Standard deviations of F-statistics were obtained through jackknifing over loci.
95% confidence intervals of F-statistics were obtained through bootstrapping over loci.


– Indices of genetic diversity per population

Population  Num Eff_num Ho  Hs  Gis
TGCP_WM3    1.261   1.183   0.142   0.141   -0.003
STT_WM186   1.186   1.132   0.088   0.108   0.183
MPO_WM483   1.194   1.136   0.097   0.109   0.110
PTP_WM732   1.095   1.068   0.056   0.051   -0.097


___________________________________________________________________

我不需要同时处理 Fst 文件和遗传多样性文件,我想从每种类型的文件中提取不同的数据。

两种文件类型的命名约定如下:

第一个文件被命名为

TrkNbr_1083n1282_L1n2_PrelimPops_02SubSampPops_Rep001_FstRslts

遗传多样性文件命名为

TrkNbr_1083n1282_L1n2_PrelimPops_02SubSampPops_Rep001_GenDivRslts

文件名的区别部分是“##SubSampPops_Rep###”部分。有 1,100 个“FstRslts”文件,这 1,100 个文件被细分为 11 组,每组 100 个文件...

02SubSampPops_Rep001
02SubSampPops_Rep002
02SubSampPops_Rep003
.
.
.
02SubSampPops_Rep100
04SubSampPops_Rep001
04SubSampPops_Rep002
04SubSampPops_Rep003
.
.
.
04SubSampPops_Rep100

同样,有 1,100 个“GenDivRslts”文件以相同的方式组织。

答案1

首先我们在命令行上定义一些有用的 shell 变量:

$ d='[0-9]'
$ pre='TrkNbr_1083n1282_L1n2_PrelimPops'
$ main="$d${d}SubSampPops_Rep$d$d$d"
$ post='GenDivRslts'
$ filename="${pre}_${main}_${post}"

使用 GNU awk

$ find . -type f -name "$filename"      |
  sort -t_ -nk5.1,5.2 -nk6.4,6.6        |
  xargs -r awk 'FNR==2{print;nextfile}' \
> new_text_file;

使用 GNU sed

$ find . -type f -name "$filename" |
  sort -t_ -nk5.1,5.2 -nk6.4,6.6   |
  xargs -r sed -se '2!d'           \
> new_text_file;

perl

$ find . -type f -name "$filename"                |
  sort -t_ -nk5.1,5.2 -nk6.4,6.6                  |
  xargs -r perl -ne 'print,close ARGV if $. == 2' \
> new_text_file;

head/tail

$ find . -type f -name "$filename" |
  sort -t_ -nk5.1,5.2 -nk6.4,6.6   |
  xargs -r \
   sh -c '
    for f
    do
     head -n 2 "$f" | tail -n 1
    done
   ' x > new_text_file;

答案2

为什么不简单地

awk 'FNR == 2' *FstRslts > NewFile

?如果命令行变得太长,请尝试按输入文件的细分对输入文件进行分组,或使用xargs分割行。

答案3

zsh版本(Mac 终端中的默认 shell):

for file in $(find . -type f -iname "*.txt"); cat "$file" | head -2 | tail -1 >> output.txt

这假设所有输入文本文件都位于同一目录中,并且处理文件的顺序并不重要。

bash版本:

for file in $(find . -type f -iname "*.txt"); do cat $file | head -2 | tail -1; done >> output.txt 

编辑1:echo没有必要 遵循纳西尔和 Steeldriver 的建议进行命令替换。以下是 awk 版本,

for file in $(find . -type f -iname "*.txt"); awk 'NR==2' $file >> output.txt

而且,如果文件没有扩展名,txt则可以使用所有文件中通用的任何模式。假设所有文件的File名称中都有,awk版本可以是

for file in $(find . -type f -iname "*File*"); awk 'NR==2' $file >> output.txt

编辑2:

根据您所提到的,您的FstRsltsGenDivRslts是文件组的唯一标识符。因此,您可以"*FstRslts"为您的FstRslts文件使用,而不是"*.txt".同样适用于GenDivRslts

笔记

我正在接受@steeldrivers的建议和课程,并添加以下内容作为答案之一(更惯用):

find . -type f -iname "*FstRslts" -exec awk 'NR==2' {} \; > output.txt

编辑3 find .- 从当前工作目录开始搜索

type -f- 搜索文件类型

-iname "*FstRslts"- 搜索与模式匹配的文件名时忽略大小写

-exec- 执行以下命令

awk 'NR==2'- 提取由于先前命令而找到的每个文件的第二行(匹配模式)

{} \;- 文件(匹配模式)命令终止的占位符

> output.txt- 将结果重定向到文件名“output.txt”

相关内容