我有两个与comm
命令进行比较的ID列表。我的问题是输出看起来像这样:
YAL002W
YAL003W
YAL004W
YAL005C
YAL008W
YAL011W
我想做的就是尝试以某种方式管道它,以便在空的spcaces中写入文件,当我在excel
中打开这些文件时转换为白色单元格。我已经尝试了所有可能的组合,我发现grep,awk和sed删除空格而没有运气...
所以我得出结论,列分别被一个或两个标签分隔,因此我不能删除它们就像删除空格一样容易,而不删除文件的格式。
欢迎任何帮助或建议。 感谢
编辑:
我希望我的输出为三列,制表符分隔,没有空格
YAL002W YAL004W YAL008W
YAL003W YAL005C
YAL011W
EDIT2避免引用XY问题:
原始问题(X):我必须列出并且我想在两个列表之间找到共同和唯一的单词(稍后生成维恩图)。所以comm
似乎是完美的解决方案,因为我同时获得了所有三个列表,稍后我可以轻松导入到excel中。
次要问题(Y):生成的三列不是三列(或者我开始思考)因为我不能cut -f
它们,我也无法删除通常为awk 'NF'
或grep .
的空格(例如)。
答案 0 :(得分:2)
鉴于此输入和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
答案 1 :(得分:1)
对于踢,没有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。
答案 2 :(得分:1)
更多踢,非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
答案 3 :(得分:0)
将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]; }'
答案 4 :(得分:0)
对于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