たとえば、5つの列を持つファイルがあります(Sybase選択クエリの結果をリダイレクトして取得します)。各列はタブ文字で区切られます。すべてのNULL列をフィルタリングする必要があります。 5つの列のうちの1つでも空にすることができます。
たとえば、ファイルの列が次のような場合:
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
現在の値はすべての行を表示します!そして、柱を切る方法もわかりません。私はシェルスクリプトの初心者ですが、続行できません。
これを行う方法を提案できますか?
答え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
(これが私がサブシェルを使用する理由です)、skip
配列をコンマで区切られた値としてawk
変数に渡します。これを使用して、split
変数を配列に戻すことができますawk
。 awk
s
次に、配列の各番号を繰り返して列を空にするように設定し、残りを印刷します。
答え3
ファイルを2回処理しない限り、これを行うことはできません。まず、次のようにして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