我一直在尝试过滤一些我长期拥有的csv文件。几乎是手工完成,因为我无法弄清楚为什么我的脚本不起作用。希望你们能弄清楚我做错了什么。
我有以下文件:csv file
我可以使用以下sed脚本替换小于1的值:
sed -e 's/[0][0-9]*\.[0-9]*/0/g' genes.csv > genes-filtered1.csv
在下一步中,我想删除所有包含全零的行。但是,如果它们在至少一列中的值大于1,我想保留。我尝试了几个脚本,但它不起作用。
以下是其中一些:
awk '{ if ($2 > 1 || $3 > 1 || $4 > 1 || $5 > 1 || $6 > 1 || $7 > 1 || $8 > 1 || $9 > 1 || $10 > 1 || $11 > 1 || $12 > 1 || $13 > 1) print $0 }' genes-filtered1.csv > genes-filtered2.csv
或者只是尝试使用阈值过滤一列:
threshold=1
awk -v threshold=$threshold '$3 > threshold' genes-filtered1.csv > genes-filtered2.csv
我也尝试过:
awk '{ for (i=2; i<=NF; i++) { if ($i != 0) { print; next } } }' genes-filtered1.csv > genes-filtered2.csv
最后我尝试了:
awk '{for (i=2;i<=NF;i++) if ($i>=1){print $0;next}}' genes-filtered1.csv > genes-filtered2.csv
问题是输出文件是空的还是与原始文件相同。任何建议如何解决它将不胜感激。还有可能有一个awk命令来执行我正在用sed做的事情,然后删除所有零的行? 谢谢
答案 0 :(得分:2)
当您使用awk
时,您并不需要使用sed
。当任何一个字段大于f
时,以下解决方案将启用标记1
。如果该标志为真,那么我们将再次遍历字段并将所有小于1
的值转换为0
:
awk '
BEGIN { FS = OFS = "," } # Set input and output field separator to ,
{
for (i=2; i<=NF; i++)
if ($i >= 1) { f = 1 } # Enable a flag when any one field is greater than 1
}
f {
for (i=2; i<=NF; i++) {
$i = ($i < 1 ? 0 : $i) # If the flag is true convert values < 1 to 0
}
f = 0; # Set the flag to false
print # Print the line
}' file
答案 1 :(得分:2)
awk '
BEGIN{ FS=OFS="," }
NR > 1 {
allZeros = 1
for (i=2; i<=NF; i++) {
if ($i < 1) {
$i = 0
}
else {
allZeros = 0
}
}
}
!allZeros
' file