如何使用 unix select 具有特定值的列
How to select columns with specific values using unix
我有以下示例制表符分隔文件:
.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 中执行此操作。有人可以帮忙吗?谢谢
你在找这个吗?
awk '{ print " " " " " " " " }' 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
你已经知道输入文件有多少行,所以只需简单地获取每列的总和并与最后一行索引减去 1(列的总和)进行比较。
#!/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
}
}'
执行此操作后,可以获得您需要的列的索引。也许这是一个简单的方法。
我认为最好的方法是读取 Excel 中的 csv 文件,计算每列的总和并手动删除不需要的列。
使用 sed 成为一种肮脏且缓慢的解决方案。
sed 解决方案的想法是将任何 0 或 1 值(@Lee:是的,我对您的 post 的评论对我也有效,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}_/" 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
我有以下示例制表符分隔文件:
.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 中执行此操作。有人可以帮忙吗?谢谢
你在找这个吗?
awk '{ print " " " " " " " " }' 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
你已经知道输入文件有多少行,所以只需简单地获取每列的总和并与最后一行索引减去 1(列的总和)进行比较。
#!/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
}
}'
执行此操作后,可以获得您需要的列的索引。也许这是一个简单的方法。
我认为最好的方法是读取 Excel 中的 csv 文件,计算每列的总和并手动删除不需要的列。
使用 sed 成为一种肮脏且缓慢的解决方案。
sed 解决方案的想法是将任何 0 或 1 值(@Lee:是的,我对您的 post 的评论对我也有效,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}_/" 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