【问题标题】:Remove blank spaces comm output删除空格 com 输出
【发布时间】:2018-04-05 21:35:28
【问题描述】:

我有两个 ID 列表,我正在与 comm 命令进行比较。我的问题是输出看起来像这样:

YAL002W
YAL003W
        YAL004W
        YAL005C
                YAL008W
        YAL011W

我想要做的就是尝试以某种方式对其进行管道传输,以便在写入文件时没有空空格,当我在excel 中打开这些文件时,这些空格会转换为白色单元格。我已经尝试了所有可能的 grep、awk 和 sed 组合来删除空格,但没有运气...
所以我得出的结论是,列分别由一个或两个制表符分隔,因此我无法删除它们就像在不删除文件格式的情况下删除空格一样容易。

欢迎任何帮助或建议。 谢谢

编辑:

我希望我的输出是三列,制表符分隔,没有空格

YAL002W YAL004W YAL008W
YAL003W YAL005C
        YAL011W

EDIT2 避免引用的 XY 问题:

原始问题 (X):我必须列出并且我想在两个列表之间找到共同和唯一的单词(稍后生成维恩图)。所以comm 似乎是一个完美的解决方案,因为我同时获得了所有三个列表,以后我可以轻松地将它们导入到 excel 中。

次要问题(Y):生成的三列不是三列(或者我开始认为),因为我不能cut -f它们,也不能用通常的@删除空格987654327@ 或 grep .(例如)。

【问题讨论】:

  • 预期的输出是什么,您尝试了什么?
  • @JuanLB 不要试图把它放在评论中,编辑问题并显示它。
  • 输出字符串与输入不匹配!
  • 您想合并不同行的列吗?为什么?
  • 有趣。有点像俄罗斯方块。每个解决方案都将是一笔财富。

标签: linux shell awk grep comm


【解决方案1】:

鉴于此输入和comm 输出:

$ cat file1
YAL002W
YAL003W
YAL008W

$ cat file2
YAL004W
YAL005C
YAL008W
YAL011W

$ comm file1 file2
YAL002W
YAL003W
        YAL004W
        YAL005C
                YAL008W
        YAL011W

这将满足您的要求:

$ cat tst.awk
BEGIN { FS=OFS="\t" }
{
    colNr = NF
    rowNr = ++rowNrs[colNr]
    val[rowNr,colNr] = $NF
    numCols = (colNr > numCols ? colNr : numCols)
    numRows = (rowNr > numRows ? rowNr : numRows)
}
END {
    for (rowNr=1; rowNr<=numRows; rowNr++) {
        for (colNr=1; colNr<=numCols; colNr++) {
            printf "%s%s", val[rowNr,colNr], (colNr<numCols ? OFS : ORS)
        }
    }
}

.

$ comm file1 file2 | awk -f tst.awk
YAL002W YAL004W YAL008W
YAL003W YAL005C
        YAL011W

当然,您可以跳过对comm 的调用并立即使用 awk:

$ cat tst.awk
BEGIN { FS=OFS="\t" }
NR==FNR {
    file1[$0]
    next
}
{
    if ($0 in file1) {
        colNr = 3
        delete file1[$0]
    }
    else {
        colNr = 2
    }
    rowNr = ++rowNrs[colNr]
    val[rowNr,colNr] = $0
}
END {
    for (v in file1) {
        colNr = 1
        rowNr = ++rowNrs[colNr]
        val[rowNr,colNr] = v
    }

    numRows = (rowNrs[1] > rowNrs[2] ? rowNrs[1] : rowNrs[2])
    numRows = (numRows   > rowNrs[3] ? numRows   : rowNrs[3])
    numCols = 3
    for (rowNr=1; rowNr<=numRows; rowNr++) {
        for (colNr=1; colNr<=numCols; colNr++) {
            printf "%s%s", val[rowNr,colNr], (colNr<numCols ? OFS : ORS)
        }
    }
}

.

$ awk -f tst.awk file1 file2
YAL002W YAL004W YAL008W
YAL003W YAL005C
        YAL011W

【讨论】:

  • 你的意思是我可以直接用awk比较两个文件?我会试试的!,谢谢!
  • @juan,你可能想要comm f1 f2 | awk -f tst.awk
  • 抱歉 n00b 问题,但 tst.awk 不能直接写入终端窗口,对吧?我必须用代码生成一个文件,然后用$ awk -f tst.awk file 运行它,对吗?
  • 不,您可以将脚本包含在单引号中,例如 comm f1 f2 | awk '{print $1}'
  • 我更新了我的答案,向您展示如何在 awk 中完成所有操作,而无需先调用 comm。
【解决方案2】:

为了踢球,在没有comm 的情况下实施。

gawk '
    NR == FNR {file1[$0]; next}
    $0 in file1 {common[$0]; delete file1[$0]; next}
    {file2[$0]}
    END {
        PROCINFO["sorted_in"] = "@ind_str_asc"
        c=0; for (e in file1)  v[1,++c] = e; max = c
        c=0; for (e in file2)  v[2,++c] = e; if (c > max) max = c
        c=0; for (e in common) v[3,++c] = e; if (c > max) max = c
        for (i=1; i<=max; i++)
            printf "%s\t%s\t%s\n", v[1,i], v[2,i], v[3,i]
    }
' file1 file2
YAL002W YAL004W YAL008W
YAL003W YAL005C 
    YAL011W 

需要 GNU awk 才能使用 PROCINFO。

【讨论】:

    【解决方案3】:

    更多精彩,非 awk 答案

    comm file1 file2 | ruby -e '
        data = Array.new(3) {Array.new}
        readlines.each {|line| 
            fields = line.chomp.split("\t")
            data[fields.length - 1] << fields[-1]
        }
        m = data.map(&:length).max
        data.collect {|lst| (lst + [""] * m).first(m)}   # pad shorter lists
            .transpose
            .each {|row| puts row.join("\t")}
    '
    
    YAL002W YAL004W YAL008W
    YAL003W YAL005C 
            YAL011W 
    

    【讨论】:

      【解决方案4】:

      使用awk 和TAB 作为字段分隔符。找到第一个填写的字段,并将其添加到多维数组的相应列中。为每一列使用单独的计数器,以便填充该数组中的下一行。

      awk -F'\t' 'BEGIN {col1=0; col2=0; col3=0; max=0; SUBSEP="\t"}
                  { if (!out[max]) {out[max,1] = ""; out[max,2] = ""; out[max,3] = ""} }
                  length($1) { out[col1, 1] = $1; if(col1 > max) max = col1++; next }
                  length($2) { out[col2, 2] = $2; if(col2 > max) max = col2++; next }
                  length($3) { out[col3, 3] = $3; if(col3 > max) max = col3++;  }
                  END { for (i = 0; i < max; i++) { print(out[i]; }'
      

      【讨论】:

        【解决方案5】:

        对于comm的输出,列数是固定的,这里有一个量身定制的解决方案

        $ awk 'BEGIN {FS=OFS="\t"}
                     {for(i=1;i<=3;i++) 
                        if($i) {a[i,++c[i]]=$i; if(max<c[i]) max=c[i]}} 
               END   {for(i=1;i<=max;i++) print a[1,i],a[2,i],a[3,i]}' file
        
        YAL002W YAL004W YAL008W
        YAL003W YAL005C
                YAL011W
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-03
          • 2022-01-14
          • 2017-07-11
          • 1970-01-01
          • 2019-06-10
          • 2023-03-16
          相关资源
          最近更新 更多