タブで区切られたテーブルがあります。
a b c
A 5 2 0
B 0 5 4
C 4 3 4
D 2 0 2
列名や行名を変更せずにゼロ以外の値を「1」に変更したいと思います。
希望の出力:
a b c
A 1 1 0
B 0 1 1
C 1 1 1
D 1 0 1
これを明確にするために、以下はサンプルテーブルです。この文字は列/行名を表す変数です。何百もの列と行があるかもしれません。ゼロ以外の値(ここでは数字で指定)は必ずしも数字である必要はありません。たとえば、人の名前です。
答え1
厳密にタブ区切りの入力を想定すると、次のようになります。
$ cat data.in
a b c
A nancy bilbo baggins 0
B 0 darcy bender
C phantom menace Unix !!
D last row 0 the end
$ cat -t data.in
^Ia^Ib^Ic
A^Inancy^Ibilbo baggins^I0
B^I0^Idarcy^Ibender
C^Iphantom menace^IUnix^I!!
D^Ilast row^I0^Ithe end
awk
タスクを実行するスクリプト:
BEGIN { OFS = FS = "\t" }
NR != 1 {
for (i = 2; i <= NF; ++i) {
if ($i != "0") {
$i = "1";
}
}
}
{ print }
実行してください:
$ awk -f script.awk data.in
a b c
A 1 1 0
B 0 1 1
C 1 1 1
D 1 0 1
スクリプトは、0
各フィールド(列)を単一文字(最初のフィールドを除く)と比較してとして0
出力します1
。出力はタブで区切られます。
答え2
sed '1!s/ [^ ]*[^ 0][^ ]*/ 1/g'
0
1つ以上の空白以外の文字を含む空白以外の文字のシーケンスは(最初の行を除く)に置き換えられます。1
IOW、これはゼロシーケンスと最初の列と行を除くすべての項目を置き換えます1
。
答え3
タイトルにあなたの例のような数字が含まれていないことを考えると、私が考える最も簡単な方法は次のとおりです。
sed 's/[1-9]/1/g' file.txt
参考範囲:1~9(0を除く)
$ echo "A 5 2 0" |sed 's/[1-9]/1/g'
A 1 1 0
この方法は、列の数が最大9の場合に機能します。そうでなく、その数が10個以上になる場合は修正する必要があります。
OPの最新の説明によると、ゼロ以外の項目は名前などになる可能性があるため、機能しません。
答え4
これはbashでのみ機能します。
bash$ paste <(cut -f1 file) <(cut -f2- file |
sed -r '1b; # if title line then skip to end
s#\t#\n#g # seperate line to multi-line
s#.*[^0].*#1#Mg # apply multi-line operation
s#\n#\t#g' ) # turn to one line
a b c
A 1 1 0
B 0 1 1
C 1 1 1
D 1 0 1