我有一个文件,比方说,有 5 列(通过重定向 Sybase 选择查询的结果获得)。每列由制表符分隔。我需要过滤掉所有 NULL 的列。五列中的任何列都可以为空。
例如,如果文件中的列如下所示:
1000 NULL NULL 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
7 NULL 1000 2 NULL
输出必须是(删除第 2 列和第 5 列后),最好在同一个文件中:
1000 NULL 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
我到了:
for i in {1..5}
do
echo $i
dlr="$"$i
str="{print $dlr}"
echo $str
awk '$str' <input_file> | while read value
do
echo $value
if [ "$value" == "NULL" ]
then
echo "inside"
cut $i
fi
done
done
现在的值,显示所有行!另外,我不知道如何切断该列。我是一个 shell 脚本初学者,无法继续下去。
您能建议如何做到这一点吗?
答案1
借助于GNU实用程序datamash
,首先反转行,然后删除所有空行并再次反转行:
$ datamash transpose | sed -Ee '/^(NULL\t)*NULL$/d' | datamash transpose
答案2
我不太喜欢这个解决方案,但它似乎有效:
#!/bin/bash
input=~/tmp/input
skip=()
c=$(awk '{print NF;exit}' "$input")
for ((i=1;i<=c;i++)); do
col=$(awk -v c="$i" '{print $c}' "$input" | sort -u)
if [[ $col == NULL ]]; then
skip+=( "$i" )
fi
done
( IFS=,; awk -v S="${skip[*]}" '{ split(S,s,","); for (i=1;i<=length(s);i++) { $s[i]="" } print}' "$input" )
input
(您的输入文件)skip
(稍后将填充的数组)c
(将设置为文件中的列数。这假设整个文件具有统一的列数)- 我们现在将循环遍历文件中的每一列,对其进行排序和唯一,并检查该列是否仅包含
NULL
.如果是这样,我们将该列号添加到skip
数组中 - 现在,我们将 设为
IFS
逗号(这是我使用子 shell 的原因),并将数组skip
作为逗号分隔值传递给awk
变量。这样我们就可以用来split
将该变量转换回数组awk
。 awk
然后将循环遍历s
数组中的每个数字并将该列设置为空并打印剩余的内容。
答案3
如果不处理文件两次就无法做到这一点。首先使用以下命令awk
构建最终cut
命令:
killnulls(){
cut -f "$(awk -F'\t' '
{ for(i=1;i<=NF;i++) a[i] += $i!="NULL" }
END { for(i=1;i in a;i++) if(a[i]) printf j++?","i:i }
' "$@")" "$@"
}
$ killnulls file
1000 NULL 2
7 1000 2
7 1000 2
...
答案4
命令:
awk '/NULL/{gsub(/NULL/,"",$0);print $0}' filename| sed -r "s/\s+/ /g"| awk 'NR==1{$3=$2;$2="NULL";}1'
输出
awk '/NULL/{gsub(/NULL/,"",$0);print $0}' i.txt| sed -r "s/\s+/ /g"| awk 'NR==1{$3=$2;$2="NULL";}1'
1000 NULL 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2
7 1000 2