Что я использую, чтобы манипулировать текстовыми файлами, извлекать из них данные и сохранять результаты в табличном формате? - PullRequest
2 голосов
/ 10 июня 2019

У меня есть текстовый файл, в котором содержатся ежедневные данные по различным акциям, идентифицированным PERMNO. Итак, текстовый файл выглядит так:

PERMNO = 1234

PERMNO = 2134

Market data:

    Date | Price | Return | Volume
    --------------------------------
    2019-01-01| 120 | 100 | 100

PERMNO = 3456

Market data:

    Date | Price | Return | Volume
    --------------------------------
    2019-01-01| 200 | 150 | 130

То, что я хочу сделать, это извлечь всю PERMNO до рыночных данных, объединить и показать ее вместе с остальными рыночными данными, добавив новый столбец PERMNO рядом с остальными данными. Так должно выглядеть примерно так:

Market data:

    Date | Price | Return | Volume | PERMNO
    -----------------------------------------
    2019-01-01| 120 | 100 | 100 | 1234,2134
    2019-01-01| 200 | 150 | 130 | 3456

Я пытаюсь использовать awk для этого. Я могу извлечь PERMNO с этим, но я не могу объединить его с остальными рыночными данными, добавив новую колонку. Подойдет любая альтернатива awk, например, sed. Но я все еще новичок в сценариях оболочки, поэтому я не знаю их полной функциональности. Кто-нибудь может подсказать, как мне поступить с этой проблемой?

Ответы [ 3 ]

2 голосов
/ 10 июня 2019

Вы можете получить то, о чем просили:

$ cat tst.awk
BEGIN { OFS=" | " }

/^PERMNO/ {
    permnos = ( permnos == "" ? "" : permnos ",") $NF
}

/^ +[[:alpha:]]/ && !doneHdr++ {
    indent = text = $0
    sub(/[^ ].*/,"",indent)
    sub(/^ +/,"",text)
    hdr = text OFS "PERMNO"
    sep = sprintf("%*s",length(hdr)+2,"")
    gsub(/ /,"-",sep)
    print "Market data:" ORS ORS indent hdr ORS indent sep
}

/^ +[0-9]/ {
    print $0, permnos
    permnos = ""
}

$ awk -f tst.awk file
Market data:

    Date | Price | Return | Volume | PERMNO
    -----------------------------------------
    2019-01-01| 120 | 100 | 100 | 1234,2134
    2019-01-01| 200 | 150 | 130 | 3456

но я настоятельно рекомендую вам просто сгенерировать CSV вместо этого для удобства дальнейшего анализа / манипуляции:

$ cat tst.awk
BEGIN { FS="[ |]+"; OFS="," }

/^PERMNO/ {
    permnos = ( permnos == "" ? "" : permnos " ") $NF
}

sub(/^ +/,"") {
    $1 = $1
    if ( /^[[:alpha:]]/ && !doneHdr++ ) {
        print $0, "PERMNO"
    }
    else if ( /^[0-9]/ ) {
        print $0, permnos
        permnos = ""
    }
}

$ awk -f tst.awk file
Date,Price,Return,Volume,PERMNO
2019-01-01,120,100,100,1234 2134
2019-01-01,200,150,130,3456

Вы всегда можете создать формат таблицы из этого, если вам нравится использовать различные инструменты, например, с column:

$ awk -f tst.awk file | column -s, -o' | ' -t
Date       | Price | Return | Volume | PERMNO
2019-01-01 | 120   | 100    | 100    | 1234 2134
2019-01-01 | 200   | 150    | 130    | 3456

и если вам нравится эта строка подчеркивания под заголовком:

$ awk -f tst.awk file | column -s, -o' | ' -t | awk '1;NR==1{gsub(/./,"-");print}'
Date       | Price | Return | Volume | PERMNO
---------------------------------------------
2019-01-01 | 120   | 100    | 100    | 1234 2134
2019-01-01 | 200   | 150    | 130    | 3456
0 голосов
/ 10 июня 2019

Вы можете сделать это следующим образом:

BEGIN {FS=" = " ; H="Market data:\n\n    Date | Price | Return | Volume | PERMNO" ; print H}
/PERMNO/ {PNO = PNO "," $2 "," }
/2[0-9]{3}-/ { gsub(",,+",",",PNO) ; gsub("^,|,$","",PNO) ; print $0 " | " PNO ; PNO = ""; next}
  1. Первая строка устанавливает разделитель поля для PERMNO строк и печатает заголовок.
  2. Строка secoind сохраняет(и добавляет) идентификаторы PERMNO (только в строках, которые соответствуют PERMNO).
  3. Третья строка выполняется, когда строка соответствует шаблону, подобному году (это может быть расширено / изменено), очищаетPNO переменная (без начальных, конечных или повторяющихся запятых), затем печатается вся строка со значением PNO.

Это можно увидеть в действии на ideone .

0 голосов
/ 10 июня 2019

Это, кажется, дает желаемый вывод (с использованием gawk 4.14):

#!/usr/bin/gawk -f
@include "join"
BEGIN { OFS="\t" }
/PERMNO/{ if(marketseen==1) {p=$3; marketseen=0} else p=p!="" ? p "," $3 : $3;  }
/Market/{ marketseen=1 }
{ split($0,a,"|");
        lc = "";
        if (a[1]~Date) lc = "PERMNO";
        if (a[1]~"0") lc = p;
        if (NF<4) lc="";
        print a[1],a[2],a[3],a[4], lc }

input:

$ cat MarketData.txt
PERMNO = 1234
PERMNO = 2134
Market data:
Date | Price | Return | Volume
--------------------------------
2019-01-01| 120 | 100 | 100
PERMNO = 3456
Market data:
Date | Price | Return | Volume
--------------------------------
2019-01-01| 200 | 150 | 130

output:

$ ./marketdata.sh MarketData.txt
PERMNO = 1234
PERMNO = 2134
Market data:
Date     Price   Return          Volume PERMNO
--------------------------------
2019-01-01       120     100     100    1234,2134
PERMNO = 3456
Market data:
Date     Price   Return          Volume PERMNO
--------------------------------
2019-01-01       200     150     130    3456
...