我有以下示例制表符分隔文件:
.CvR Col_1 Col_2 Col_3 Col_4 Col_5
S1 1 0 1 0 1
S2 1 1 1 0 1
S3 1 1 1 1 1
S4 1 0 1 1 1
S5 1 0 1 1 1
我试图想出一个简单的方法来打印第一列和所有列,只需" 1"其中的价值观。
我想要的输出文件应如下所示:
.CvR Col_1 Col_3 Col_5
S1 1 1 1
S2 1 1 1
S3 1 1 1
S4 1 1 1
S5 1 1 1
我的实际输入文件会更大。我想尽可能在UNIX中这样做。有人可以帮忙吗?感谢。
答案 0 :(得分:2)
你已经知道输入文件的行数,所以只需获取每个col的总和,并与最后一行索引减去1(col的总和)进行比较。
#!/bin/bash
# colSum is the last line index minus 1
cat input.txt | awk -v colSum=5 '{
NR != 1
for (i = 2; i <= NF; ++i) {
sumOfCol[i] += $i
}
}
END {
for (i in sumOfCol) {
if (sumOfCol[i] == colSum)
print i
}
}'
执行此操作后,可以获得col的索引。也许这是一个简单的方法。
答案 1 :(得分:1)
你在找这个吗?
awk '{ print $1 " " $2 " " $4 " " $6 " " }' file
.CvR Col_1 Col_3 Col_5
S1 1 1 1
S2 1 1 1
S3 1 1 1
S4 1 1 1
S5 1 1 1
答案 2 :(得分:1)
我认为最好的方法是在Excel中将文件作为csv文件读取,计算每列的总和并手动删除不需要的列。
使用sed成为一个肮脏而缓慢的解决方案。
sed解决方案的想法是将任何0或1值(@Lee:是的,我对你的帖子的评论对我有效,awk似乎是一个更好的解决方案)更改为具有列号和值的字段。
您可以计算找到值1的频率,并在未匹配总行数时删除该列。
变量值包含一个将与0或1匹配的表达式,并将存储在\ 1构造的内存中。
#!/bin/bash
clear
value='\([01]\)'
cp file file2
for i in 1 2 3 4 5 6; do
sed -i "s/ ${value}/ val${i}_\1/" file2
done
rowcount=$(wc -l <file2)
for i in 1 2 3 4 5 6; do
if [ $(grep -c val${i}_1 file2) -eq ${rowcount} ]; then
sed -i "s/val${i}_./1/" file2
else
sed -i "s/Col_${i}//" file2
sed -i "s/val${i}_.//" file2
fi
done
cat file2