我有数以万计的目录。每个目录都按数字命名,例如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"}'