次の特定のテキストを含む列を削除するオプションを探しています。
「ディディ」
aaa bbb ccc ddd eee fff
1 2 3 4 5 6
2 3 4 5 6 0
したがって、出力は次のようになります。
aaa bbb ccc eee fff
1 2 3 5 6
2 3 4 6 0
私は列4を削除し、同じことを行う簡単なオプションがあることを知っていますが、私の* .csvファイルはソートされません。どんなアイデアがありますか?
ベストアンサー1
sed
正しいツールではありません。努力するawk
:
$ awk -v OFS='\t' 'NR==1{for (i=1;i<=NF;i++)if ($i=="ddd"){n=i-1;m=NF-(i==NF)}} {for(i=1;i<=NF;i+=1+(i==n))printf "%s%s",$i,i==m?ORS:OFS}' file
aaa bbb ccc eee fff
1 2 3 5 6
2 3 4 6 0
削除したい文字列(ddd
この例では)が最初の行のフィールドとして表示されるとします。
どのように動作しますか?
-v OFS='\t'
これにより、出力フィールド区切り文字がタブに設定されます。他のものを使用している場合は、この設定を変更してください。
NR==1{for (i=1;i<=NF;i++)if ($i=="ddd"){n=i-1;m=NF-(i==NF)}}
これにより、最初の行のすべての列が検索されます。 (マイナス1)として列番号を
ddd
変数に保存しますn
。m
最後の列の番号にも設定されますが、i
最後の列の場合に設定されますNF-1
。for(i=1;i<=NF;i+=1+(i==n))printf "%s%s",$i,i==m?ORS:OFS
ddd
これにより、最初の行に表示されるフィールドがスキップされ、すべてのフィールドが印刷されます。i+=1
i
ループを通過するたびに1ずつ増加します。各ループで1i+=1+(i==n)
ずつ増加しますi
。ただし、i==n
この場合はi
2ずつ増加します。これは右側の列をスキップする効果があります。printf "%s%s",$i,i==m?ORS:OFS
最後の列であるかどうかに応じて、i
列区切り文字OFS
または行区切り文字の後に続く列を印刷します。ORS
i
複数行
このようなコマンドを複数行で書くことを好む人のために:
awk -v OFS='\t' '
NR==1{
for (i=1;i<=NF;i++)
if ($i=="ddd") {
n=i-1
m=NF-(i==NF)
}
}
{
for(i=1;i<=NF;i+=1+(i==n))
printf "%s%s",$i,i==m?ORS:OFS
}
' file
カンマ区切りファイルの使用
入力と出力をコンマで区切るには、入力フィールド区切り記号(使用-F
)と出力フィールド区切り記号を変更する必要があります。たとえば、次の入力ファイルを考えてみましょう。
$ cat file2
aaa,bbb,ccc,ddd,eee,fff
1,2,3,4,5,6
2,3,4,5,6,0
次に、次を使用します。
$ awk -F, -v OFS=, 'NR==1{for (i=1;i<=NF;i++)if ($i=="ddd"){n=i-1;m=NF-(i==NF)}} {for(i=1;i<=NF;i+=1+(i==n))printf "%s%s",$i,i==m?ORS:OFS}' file2
aaa,bbb,ccc,eee,fff
1,2,3,5,6
2,3,4,6,0