2 番目の項目を消したい

awk print から引用します。 「タブ区切りの項目が10個並んでいて、2番目の項目を消したい。」ということですが、どういう方法があるでしょうか?

個人的には愚直に

$ gawk -F'\t' '{print $1"\t \t"$3"\t"$4"\t"$5"\t"$6"\t"$7"\t"$8"\t"$9"\t"$10}' xxx.list

という方法は悪くないと思いますが、毎回 "\t" を入力するのも面倒なので、最初に思いついたものは以下のものです。

$ gawk -F'\t' -v OFS='\t' '{print $1, " ", $3, $4, $5, $6, $7, $8, $9, $10}' xxx.list

確かに for ループで書く方法もあるのですが、実際には長くなってしまいます。

$ gawk '{for (i = 1; i <= NF; i++){printf("%s\t", $i)}} END{print ""}' xxx.list

しかも、この場合には最後にタブが余計に付いてしまいます。

こういう場合には awk の持つ「自動再構築」を利用します。 具体的には以下のようなスクリプトです。

$ gawk -v OFS='\t' '$2=" "' xxx.list

多分最短だと思いますが、この一見意味不明な条件式にはいろいろな意味があります。 代入式が条件式になっていることに不思議だと思う人もいるでしょうが、これは awk のパターン - アクションのパターンに該当します。

$2=" " は代入であり、awk の場合には破壊的に (代入先に値があっても無視されて) 代入されますので、この代入は常に成立します。 つまり代入による戻り値は真になります。 パターンが真の時にアクションが何も指定されていない場合には、print $0 と等価になりますから、自動的に出力されます。 また、$2 に値が代入されたことを受けて awk はアクションに入る前に自動的に $0 を再構築し、$1"\t \t"$3"\t"$4"\t"$5"\t"$6"\t"$7"\t"$8"\t"$9"\t"$10 と同じ文字列が $0 に格納されます。

同様に以下のようなものも成立します。

$ gawk -v OFS='\t' 'sub(/.*/," ",$2)' xxx.list

こちらも知られていない場合が多いのですが、sub() 関数は置換に成功すると真を返しますので、同様の結果になります。

この再構築を使いこなすことは慣れないと難しいのですが、慣れてしまうとアクションのない一行野郎でも多くのことをこなすことができると分かることでしょう。

tag_nawk.pngtag_nawk.pngtag_nawk.pngtag_nawk.png