【发布时间】:2016-07-21 21:17:23
【问题描述】:
我想连接两个共享一些但不是所有列标题的 ascii 表(一个在另一个之下),并且我想用一些字符串替换“空白”,例如输出中的“nan”。 (相关:can we do this with emacs,但目前还没有答案)
例如
表 1
Head1 HeadA
1 a
2 b
表 2
HeadA HeadFoo
c bar
结果是
Head1 HeadA HeadFoo
1 a nan
2 b nan
nan c bar
我编写了以下非常新鲜的 zsh 脚本(使用一个仅 zsh 命令),但是当有很多列时它慢(原因很明显)。
请注意,上面我使用制表符分隔的示例,但我的脚本需要空格分隔的表格。
#!/bin/zsh
#
# take several dat files, possibly with different headers
#
containsElement () {
local e
for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
return 1
}
ALL_COLUMNS=()
for A in "$@"; do
if [ ! -f ${A} ]
then
echo not a file
exit
fi
ALL_COLUMNS=("${ALL_COLUMNS[@]}" `head -1 "${A}"`)
done
typeset -U ALL_COLUMNS
echo $ALL_COLUMNS
for A in "$@"; do
HEADER=($(head -1 "${A}"))
TMP="_TMP_${A}_"
TMPFILE="_TMPFILE"
#create empty temporary files (/hack)
touch "${TMPFILE}"
touch "${TMP}"
rm "${TMP}"
rm "${TMPFILE}"
touch "${TMPFILE}"
touch "${TMP}"
for C in ${ALL_COLUMNS[@]}; do
if ! containsElement "${C}" "${HEADER[@]}"
then
"${C}" not in "${HEADER[@]}"
#paste a column of nans to TMPFILE
paste "${TMP}" <(sed '1d;s/.*/nan/' "${A}") > "${TMPFILE}"
cat "${TMPFILE}" > "${TMP}"
else
# echo "${C}" is in "${HEADER[@]}"
#find which column this is, cut it, and paste it to TMPFILE
COUNT=1
for H_KEY in $(head -1 ${A}); do
if [ "${C}" = "${H_KEY}" ]; then
break
else
let COUNT=COUNT+1
fi
done
paste "${TMP}" <(cut -d " " -f${COUNT} <(sed '1d' ${A})) > "${TMPFILE}"
cat "${TMPFILE}" > "${TMP}"
fi
done
#cat the current input file to stdout, with any additional nan columns.
#remove leading white space left by paste
sed 's/^[[:space:]]*//' "${TMP}"
rm "${TMP}"
done
编辑:这里还有两个输入文件(这次用空格分隔)来尝试。
% cat test1.dat
A B C
1 2 3
% cat test2.dat
A B D
1 2 4
% ./collate_dat_files_different_headers.sh test2.dat test1.dat
A B D C
1 2 4 nan
1 2 nan 3
这是一组更大的输入(如果您在自己的脚本上尝试,请注意空格分隔的输入。):
% ROWS=10; (echo A B C D E F G && seq $ROWS > _tmp && paste _tmp _tmp _tmp _tmp _tmp _tmp _tmp | sed 's/\t/ /g') > bigtest.dat
% cat bigtest.dat
A B C D E F G
1 1 1 1 1 1 1
2 2 2 2 2 2 2
3 3 3 3 3 3 3
4 4 4 4 4 4 4
5 5 5 5 5 5 5
6 6 6 6 6 6 6
7 7 7 7 7 7 7
8 8 8 8 8 8 8
9 9 9 9 9 9 9
10 10 10 10 10 10 10
% cut -d" " -f1,2,5,7 bigtest.dat > bigtest1.dat
% cut -d" " -f1,2,4,7 bigtest.dat > bigtest2.dat
% cut -d" " -f1,2 bigtest.dat > bigtest3.dat
% cut -d" " -f7,6,4,2,3,1 bigtest.dat > bigtest4.dat
% ./collate_dat_files_different_headers.sh bigtest1.dat bigtest2.dat bigtest3.dat bigtest4.dat
A B E G D C F
1 1 1 1 nan nan nan
2 2 2 2 nan nan nan
3 3 3 3 nan nan nan
4 4 4 4 nan nan nan
5 5 5 5 nan nan nan
6 6 6 6 nan nan nan
7 7 7 7 nan nan nan
8 8 8 8 nan nan nan
9 9 9 9 nan nan nan
10 10 10 10 nan nan nan
1 1 nan 1 1 nan nan
2 2 nan 2 2 nan nan
3 3 nan 3 3 nan nan
4 4 nan 4 4 nan nan
5 5 nan 5 5 nan nan
6 6 nan 6 6 nan nan
7 7 nan 7 7 nan nan
8 8 nan 8 8 nan nan
9 9 nan 9 9 nan nan
10 10 nan 10 10 nan nan
1 1 nan nan nan nan nan
2 2 nan nan nan nan nan
3 3 nan nan nan nan nan
4 4 nan nan nan nan nan
5 5 nan nan nan nan nan
6 6 nan nan nan nan nan
7 7 nan nan nan nan nan
8 8 nan nan nan nan nan
9 9 nan nan nan nan nan
10 10 nan nan nan nan nan
1 1 nan 1 1 1 1
2 2 nan 2 2 2 2
3 3 nan 3 3 3 3
4 4 nan 4 4 4 4
5 5 nan 5 5 5 5
6 6 nan 6 6 6 6
7 7 nan 7 7 7 7
8 8 nan 8 8 8 8
9 9 nan 9 9 9 9
10 10 nan 10 10 10 10
我的问题:是否有更快/更好的方法来执行此操作或改进我的脚本?
【问题讨论】:
-
你看过
paste、join或column吗? -
我不认为 join 是我想要的,因为它会合并表而不是 cat 它们。 paste 在我上面的脚本中,并且 column 可能有助于将东西放在一起(就像 paste 一样),但我不知道它会如何加快脚本的速度。不过很高兴知道这些。
-
最后一个Result不应该是
nan c bar?? -
正确。对此感到抱歉。
标签: bash shell zsh data-manipulation zshrc