0

相关问题:https ://stackoverflow.com/posts/18164848

输入文件 input.txt 是一个制表符分隔的 unicode txt

a  A   e  f  m
b  B   g  h
c  C   i  j
b  B   k  l

我想匹配第一列和第二列并合并。所以我想得到 output.txt

a  A   e  f  m
b  B   g  h     k  l
c  C   i  j

代码必须检测输入中的最大列数。因为在这个例子中是 5,所以“k l”是从第 6 列开始的。

实际上,当它们都是数字时,我几乎设法使用 Matlab 做到了这一点。但是哦,当它们是字母时,Matlab 在处理 unicode 方面非常糟糕,尽管我读了 stackoverflow 关于如何在 Matlab 中处理 unicode 我放弃了。所以我现在转向python。

https://stackoverflow.com/posts/18164848的Nirk回应说,下面的行就可以了。

awk -F\t '{a=$1 "\t" $2; $1=$2=""; x[a] = x[a] $0} END {for(y in x) print y,x[y]}'

但是,此代码似乎没有指定输入和输出文件。

4

3 回答 3

3

awk 是基于管道的 linux 命令。要提供输入文件并获取输出,您可以这样做: awk -F\t '{a=$1 "\t" $2; $1=$2=""; x[a] = x[a] $0} END {for(y in x) print y,x[y]}' < INPUT.TXT > OUTPUT.TXT

但是,上面的 awk 程序很难满足您的需求“代码必须检测输入中的最大列数。由于在此示例中为 5,因此从第 6 列放置了“k l”。”。

你可以试试这个python程序:

max_value_fields = 0
values = dict()

with file("input.txt") as f:
    keys = []
    for line in f:
        line    = line.strip()
        fs      = line.split('\t')

        key = '%s\t%s' % (fs[0], fs[1])
        if key not in values:
            values[key] = list()
            keys.append(key)
        values[key].append(fs[2:])

        value_fields = len(fs) - 2
        if value_fields > max_value_fields:
            max_value_fields = value_fields

with file("output.txt", 'w+') as f:
    for key in keys:
        fields = [key]
        for value_list in values[key]:
            fields.extend([value for value in value_list])
            fields.extend(['' for i in xrange(max_value_fields - len(value_list))])
        print >> f, '\t'.join(fields)
于 2013-08-11T06:35:12.897 回答
2

I would read the data twice: a 1st pass for identifying the maximum number of columns, then merge rows in the 2nd pass. Results are printed (basically in random order) in the END.

awk -f script.awk infile infile > outfile

$ cat script.awk 
# BEGIN block: separators
BEGIN { FS = OFS = "\t" }

# Loop #1: detect maximum number of columns
NR == FNR { max = NF > max ? NF : max ; next }

# Loop #2: merge rows
{
    k = $1 FS $2

    if (k in a) {
        for (i = 3; i <= NF; i++) {
            a[k] = a[k] OFS $i
        }
    } else {
        NF = max
        a[k] = $0
    }
}

# END block: Print results
END { for (i in a) print a[i] }
于 2013-08-11T07:32:46.937 回答
1

尝试这个:

awk '{x=$1FS$2;$1=$2="";a[x]=a[x]?a[x]FS$0:$0}END{for(x in a) print x,a[x]}' input.txt
于 2013-08-11T04:52:00.790 回答