我几乎是这方面的初学者,并且在处理.dat文件时遇到了麻烦。我有很多.dat文件(a_“number”_b.dat),每个包含4列,我想通过for循环从每个列中抽出第2列和第4列,并将它们水平合并到一个新文件中,即挑出列每个循环并将它们并排添加到文件中。我尝试使用awk | paste语句和cut | paste语句,但根本没有使用它。在awk的情况下,我最终得到的文件只包含在循环中读取的最后一个文件中的第2列和第4列,并且剪切|粘贴给了我一个空白文件。这是我使用的代码:
phpinfo()
输入和输出示例:
for k in {1..9}
do
awk '{print $2,$4}' a_0"$k"_b.dat > atest.dat
paste atest.dat atestf.dat > atestf.dat
#cut -f2 a_0"$k"_b.dat | paste atest.dat
#cut -f4 a_0"$k"_b.dat | paste atest.dat
done
编辑:我忘了提到一些文件底部缺少行,而且当并排放置列时我不得不将它们留作空格。
答案 0 :(得分:0)
这个似乎工作正常:
for ((k=1;k<=2;k++));do
tmp="$(cat mergefile)"
paste -d ' ' <(echo "$tmp") <(cut -d ' ' -f2,4 "file$k") > mergefile
done
cat mergefile
#Output
10 1000 50 5000
20 2000 60 6000
30 3000 70 7000
40 4000 80 8000
Cut default delimiter is tab,您需要明确指定空格作为分隔符。
同样适用于粘贴。
您无法打开文件进行阅读,也无法在同一时间进行书写。
因此,您的初始尝试paste atest.dat atestf.dat > atestf.dat
失败,因为文件atestf.dat
被打开以供过去阅读,甚至用于使用&gt;进行书写。 (输出重定向)。这就是我使用tmp变量加载我的解决方案中mergefile
中已存在的数据的原因。
答案 1 :(得分:0)
a_1_b.dat a_2_b.dat
| |
V V
1 10 100 1000 5 50 500 5000
2 20 200 2000 6 60 600 6000
3 30 300 3000 7 70 700 7000
4 40 400 4000 8 80 800 8000
# script.sh
dat_files=( $(find -E . -type f -maxdepth 1 -regex '^.*\/a_[0-9]+_b\.dat$') )
for line_number in $(seq 1 $(wc -l < ${dat_files[0]}))
do
for file in ${dat_files[@]}
do
awk -v l=$line_number 'BEGIN {ORS=" "} NR==l {print $2, $4}' "$file"
done
echo
done
dat_files=...
行将所有匹配的文件存储到一个数组中。数组中的所有文件都符合以下条件......
-type f
)^.*\/a_[0-9]+_b\.dat$
^.*\/a_
) - 以a_
[0-9]+
) - 后跟一个或多个数字_b
) - 后跟_b
\.dat
) - 以.dat
外部for
循环从1
迭代到第一个匹配文件(wc -l
)中的行数(${dat_files[0]}
)。这假设所有文件具有相同的行数。因此,如果文件有20行,则外循环从1
迭代到20
。
内部for
循环迭代所有匹配的文件并输出字段/列2和4,在每行的末尾添加一个空格而不是每次迭代的换行符(OFS=' '
)。这样下一个文件的字段2和4(下一次迭代)就在前面字段的右边而不是在它们下面。
这就是它的全部!
./script.sh > result.txt
10 1000 50 5000
20 2000 60 6000
30 3000 70 7000
40 4000 80 8000