Awk или Gawk для сопоставления и слияния данных

Связанный вопрос: 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 так плохо справлялся с юникодом, хотя я читал stackoverflow о том, как работать с юникодом в Matlab, я сдался. Итак, теперь я обратился к python.

Нирк на https://stackoverflow.com/posts/18164848 ответил, что подойдет следующая строка.

awk -F\t '{a=$1 "\t" $2; $1=$2=""; x[a] = x[a] $0} END {for(y in x) напечатать y,x[y]}'

Однако этот код, похоже, не указывает входной и выходной файл.


person user1849133    schedule 11.08.2013    source источник


Ответы (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, «k l» были помещены из 6-го столбца».

Вы можете попробовать эту программу 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)
person Paul Chan    schedule 11.08.2013
comment
Спасибо! Это сработало, но кажется, что он не может читать текст в Юникоде? Я терпел неудачу при вводе текста в юникоде, и когда я изменил это на UTF-8, это сработало. Может ли он работать во всех видах ввода txt? - person user1849133; 11.08.2013
comment
Есть два способа: во-первых, вы можете использовать команду iconv для изменения кодировки текста на UTF-8 перед обработкой; во-вторых, вместо этого вы можете использовать кодеки мудьюле для открытия файла. codecs.open имеет специальный аргумент для указания кодировки текста. - person Paul Chan; 11.08.2013

Я бы прочитал данные дважды: первый проход для определения максимального количества столбцов, а затем объединил строки во втором проходе. Результаты печатаются (в основном в случайном порядке) в 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] }
person Hermann    schedule 11.08.2013

Попробуй это:

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
person jaypal singh    schedule 11.08.2013
comment
@jaypal_singh Спасибо, но это не сработало для моего реального примера. То, что я написал, было просто примером. Для моего реального примера, который слишком велик, чтобы публиковать его здесь, я просто добавил в ваш код файл output.txt. И результат казался не близким к желаемому результату. Также я думаю, что это не удается сделать Unicode txt с разделителями табуляции. Был вопрос о выводе с разделителями табуляции на stackoverflow.com/ questions/5374239/tab-separated-values-in-awk Но я не мог применить это к своей ситуации. - person user1849133; 11.08.2013