我正在使用Fedora,而bash用我拥有的文件进行一些文本操作。我正在尝试组合大量文件,每个文件都有两列数据。从这些文件中,我想提取文件第二列的数据,并将其放在一个文件中。以前,我使用了以下脚本:
paste 0_0.dat 0_6.dat 0_12.dat | awk '{print $1, $2, $4}' >0.dat
但随着文件数量的增加,这非常困难 - 尝试使用100个文件。所以我浏览了网页,看看是否有办法以一种简单的方式实现这一目标,但是空手而归。
如果可能的话,我想调用'for'循环 - 例如,
for i in $(seq 0 6 600)
do
paste 0_0.dat | awk '{print $2}'>>0.dat
done
但是这当然不能用于粘贴命令。
如果您对如何做我想做的事情有任何建议,请告诉我。
数据文件#1如下所示(由空格分隔)
-180 0.00025432
-179 0.000309643
-178 0.000189226
.
.
.
-1 2E-5
0 1.4E-6
1 0.00000
.
.
.
178 0.0023454268
179 0.002352534
180 0.001504992
数据文件#2
-180 0.0002352
-179 0.000423452
-178 0.00019304
.
.
.
-1 2E-5
0 1.4E-6
1 0.00000
.
.
.
178 0.0023454268
179 0.002352534
180 0.001504992
第一列从-180到180,增量为1.
DESIRED (n是列数;和文件数)
-180 0.00025432 0.00025123 0.000235123 0.00023452 0.00023415 ... n
-179 0.000223432 0.0420504 0.2143450 0.002345123 0.00125235 ... n
.
.
.
-1 2E-5
0 1.4E-6
1 0.00000
.
.
.
179 0.002352534 ... n
180 0.001504992 ... n
谢谢,
答案 0 :(得分:2)
join
可以获得您想要的结果。
join <(sort -r file1) <(sort -r file2)
[jaypal:~/Temp] cat file1
-180 0.00025432
-179 0.000309643
-178 0.000189226
[jaypal:~/Temp] cat file2
-180 0.0005524243
-179 0.0002424433
-178 0.0001833333
[jaypal:~/Temp] join <(sort -r file1) <(sort -r file2)
-180 0.00025432 0.0005524243
-179 0.000309643 0.0002424433
-178 0.000189226 0.0001833333
要一次执行多个文件,可以将其与find
命令 -
find . -type f -name "file*" -exec join '{}' +
答案 1 :(得分:1)
根据您在上述评论中看到的假设,您不需要粘贴。试试这个
awk '{
arr[$1] = arr[$1] "\t" $2 };
END {for (x=-180;x<=180;x++) print x "\t" arr[x]
}' *.txt \
| sort -n
请注意,我们只是根据第一个字段中的值将所有值放入数组中,并根据$ 1键附加值。读入所有数据后,END部分打印出键和值。我添加了"x="
,":vals= "
之类的内容来帮助'解释'正在发生的事情。删除那些完全干净的标签分隔数据。如果需要,将'\ t'更改为':'或'|',或者...... shudder','。将*.txt
更改为您的每个文件规范。
请注意,所有Unix命令行都限制了可在1次调用中处理的文件名的数量和大小(文件名长度,而不是内部数据)。如果您收到有关该错误消息,请告诉我们。
要排序的管道确保数据按列1排序。
使用我的测试数据,输出
-178 0.0001892261 0.0001892262 0.0001892263 0.000189226
-179 0.0003096431 0.0003096432 0.0003096433 0.000309643
-180 0.000254321 0.000254322 0.000254323 0.00025432
178 0.0001892261 0.0001892262 0.0001892263 0.000189226
179 0.0003096431 0.0003096432 0.0003096433 0.000309643
180 0.000254321 0.000254322 0.000254323 0.00025432
基于4个输入文件。
我希望这会有所帮助。
P.S。欢迎使用StackOverflow(SO)请记住阅读常见问题解答,http://tinyurl.com/2vycnvr,使用灰色三角形http://i.imgur.com/kygEP.png投票选出好的Q / A,并接受解决问题的答案,如果有的话,勾选复选标记http://i.imgur.com/uqJeW.png
答案 2 :(得分:1)
这个怎么样:
paste "$@" | awk '{ printf("%s", $1);
for (i = 2; i < NF; i += 2)
printf(" %s", $i); printf "\n";
}'
这假设您没有遇到paste
的限制(检查它可以有多少个打开的文件)。 "$@"
符号表示'给出的所有参数,与给定完全相同'。 awk
脚本只是从每行粘贴的输出中打印$1
,然后是偶数列;然后换行。它不验证奇数列是否全部匹配;这样做可能是明智的,你可以在awk
中编写一个模糊的类似循环。它也不会检查此行上的字段数是否与前一行中的字段数相同;这是另一个合理的检查。但这确实可以在所有文件的一次传递中完成整个工作 - 对于基本上任意的文件列表。
我有100个输入文件 - 如何使用此代码打开这些文件?
您将原始答案放在脚本'filter-data'中;使用seq
生成的101个文件名调用脚本。 paste
命令将所有101个文件粘贴在一起; awk
命令选择您感兴趣的列。
filter-data $(seq --format="0_%g.dat" 0 6 600)
具有该格式的seq
命令将列出101个文件名;这些是将要粘贴的101个文件。
你甚至可以没有filter-data
脚本:
paste $(seq --format="0_%g.dat" 0 6 600) | awk '{ printf("%s", $1);
for (i = 2; i < NF; i += 2)
printf(" %s", $i); printf "\n";
}'
我可能会使用更通用的脚本作为主脚本,如果需要,我会创建一个'one-liner',用当前感兴趣的特定参数集调用主脚本。
另一个可能是障碍的关键点:paste
不仅限于2个文件;它可以粘贴尽可能多的文件,你可以打开(给予或约3)。
答案 3 :(得分:0)
这可能对您有用:
echo *.dat | sed 's/\S*/<(cut -f2 &)/2g;s/^/paste /' | bash >all.dat