在许多不同的文件中查找块模式并有选择地从中提取某些行

在许多不同的文件中查找块模式并有选择地从中提取某些行

我有数以万计的目录。每个目录都按数字命名,例如1, 2, 3,... 每个目录都包含一个名为的大型 .dat 文件data.dat,每个文件都有一个如下所示的部分:

Configurations for Sm:

  Sm Nd H  O 

  0  1  4  0          1.00          7.14%
  1  0  3  0          3.00          7.14%
  0  0  5  0          1.00          7.14%

我关心每行的前两个数字。我想:

  • 所有以(在本例中,这是数字的第一行)开头的行都以该行开头的文件名(数字)命名的0 1新文件结束。0-1.dat下面是一个示例,称为“示例”。
  • 同样,以(此处为第二行)开头的所有行都应以该行开头的文件号调用的1 0文件结束。1-0.dat
  • 所有以(此处为第三行)开头的行0 0都应转到名为0-0.dat.

查找我需要的线路的复杂性是:

  • 有时,其中一行可能会丢失,或者行的顺序可能不同。
  • 此外,每个文件都有许多名为 的部分Configurations for X,其中 X 是某个字符串。所以我确实需要以某种方式使用标识符Configurations for Sm:并搜索其下面的第一组数字。

我想要实现的示例,其中该行的第一个数字是包含从中提取该行的文件的目录名称/编号:

Example
In file called 0-1.txt:
1    0  1  4  0          1.00          7.14%
2    0  1  7  1          1.00          7.14%
3    0  1 ....

In file called 1-0.txt:
1    1  0  1  0          1.00          7.14%
2    1  0  4  2          1.00          7.14%
3    1  0 ....

我目前有:

find . -name data.dat -exec grep "Configurations for Sm:" {} + > 0-1.txt

不过,所有这些都是将后面的任何内容Configurations for Sm:放在一个单独的文件中。我只是不知道如何做我需要做的事情——Configurations for Sm:按数字内容查找下面的行。如果有人有任何提示或可以引导我访问在线资源,我将非常感激。谢谢。

答案1

sed我认为你可以使用和的组合grep

假设您的所有目录0, 1, 2,... 都在/your/path(例如/your/path/0/data.dat)中:

for dir in /your/path/*; do
    idx=$(basename ${dir})
    sed -n '/Configurations for Sm:/,/Configurations for/p' ${dir}/data.dat | \
        grep '^ \+0 \+1' | \
        sed "s/^/${idx}/" >> "0-1.dat"
done

第一个sed应该仅提取文件中感兴趣的部分(在两个模式Configurations for Sm:和之间Configurations for

grep匹配0 1行首(中间有正数的空格)

第二个 sed 在行的开头添加“index”(目录名称)。

输出将附加 ( >>) 到“0-1.dat”。

您可以添加一个外循环来测试0和的不同组合1

注意:我还没有正确测试过这一点。

答案2

awk解决办法怎么样

awk '/^ *[0-1] +[0-1]/{
    n=split(FILENAME,d,"/");print d[n-1], $0 > $1"-"$2".txt"
}' $(find . -name "*.dat")

首先,将find所有dat文件提供给它们,awk但仅处理以 0 或 1 开头的行^作为前 2 个非空白字符

/^ *[0-1] +[0-1]/

然后split将文件名放入/一个数组中,将数组中的元素数量存储在n

n=split(FILENAME,d,"/")

最后将目录名称/编号(这是d[n-1]数组中的元素)和dat文件中的数据打印$0到由前两个值组成的文件中

print d[n-1], $0 > $1"-"$2".txt"

如果您有数十或数千个文件,那么每行的开销split可能FILENAME太大,在这种情况下,您可以循环遍历每个文件awk并附加到整理文件>> $1"-"$2".txt"

或许....

find . -iname "*.dat" -print0 | xargs -0  -n 1 -P 0 awk 'NR==1{n=split(FILENAME,d,"/"); dir=d[n-1]}/ *[0-1] +[0-1]/{print dir, $0 >> $1"-"$2".txt"}'

相关内容