将所有非零结果替换为“1”以形成存在/不存在

将所有非零结果替换为“1”以形成存在/不存在

我有一个制表符分隔的表格

  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(第一个字段除外)进行比较,并01.输出将以制表符分隔。

答案2

sed '1!s/ [^ ]*[^ 0][^ ]*/ 1/g'

将用(第一行除外)替换包含至少一个除0空格之外的字符的任何非空格字符序列。1

IOW,这将替换除 0 序列和第一列和第一行以外的任何内容1

答案3

考虑到标题不包含像您的示例这样的数字,我能想到的最简单的方法是:

sed 's/[1-9]/1/g' file.txt

注意范围:1 到 9,零除外。

$ 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

相关内容