Найти все уникальные столбцы из огромного (с миллионами записей и столбцов) файла OFS (без фиксированной строки заголовка) unix - PullRequest
0 голосов
/ 27 августа 2018

Введите

119764469|14100733//1,k1=v1,k2=v2,STREET:1:1=NY
119764469|14100733//1,k1=v1,k2=v2,k3=v3 
119764469|14100733//1,k1=v1,k4=v4,abc.xyz:1:1=nmb,abc,po.foo:1:1=yu

k1 может быть любым именем с буквенно-цифровым знаком. &: специальные символы, такие как abc.nm.1: 1

Ожидаемый результат (все уникальные столбцы), сортировка не требуется / не нужна, она должна быть очень быстрой

k1,k2,STREET:1:1,k3,k4,abc.xyz:1:1

Мой текущий подход / решение

awk -F',' '{for (i=0; i<=NR; i++) {for(j=1; j<=NF; j++){split($j,a,"="); print a[1];}}}' file.txt | awk '!x[$1]++' | grep -v '|' | sed -e :a -e '$!N; s/\n/ | /; ta'

Работает нормально, но слишком медленно для огромного размера файла (который может быть в МБ или в ГБ)

ПРИМЕЧАНИЕ. Это необходимо при переносе данных, следует использовать базовые команды оболочки Unix, так как в производственной среде могут не использоваться сторонние утилиты.

Ответы [ 3 ]

0 голосов
/ 27 августа 2018

не уверен насчет скорости, но попробуйте

$ cut -d, -f2- file |        # select the key/value pairs
  tr ',' '\n'       |        # split each k=v to its own line
  cut -d= -f1       |        # select only keys
  sort -u           |        # filter uniques
  paste -sd,                 # serialize back to single csv line

abc.xyz:1:1,k1,k2,k3,k4,STREET:1:1

Я ожидаю, что это будет быстрее, чем grep, так как не используется регулярное выражение.

0 голосов
/ 27 августа 2018

Если вам не нужно выводить все в одну строку:

$ awk -F'[,=]' '{for (i=2;i<=NF;i+=2) print $i}' file | sort -u
abc.xyz:1:1
k1
k2
k3
k4
STREET:1:1

Если вы делаете:

$ awk -F'[,=]' '{for (i=2;i<=NF;i+=2) print $i}' file | sort -u |
    awk -v ORS= '{print sep $0; sep=","} END{print RS}'
abc.xyz:1:1,k1,k2,k3,k4,STREET:1:1

Вы можете сделать все это одним скриптом awk, но я не уверен, что он будет столь же эффективным, как описано выше, или может столкнуться с проблемами с памятью, если / когда массив увеличится до миллионов значений:

$ cat tst.awk
BEGIN { FS="[,=]"; ORS="" }
{
    for (i=2; i<=NF; i+=2) {
        vals[$i]
    }
}
END {
    for (val in vals) {
        print sep val
        sep = ","
    }
    print RS
}

$ awk -f tst.awk file
k1,abc.xyz:1:1,k2,k3,k4,STREET:1:1
0 голосов
/ 27 августа 2018

Используйте grep -o для поиска только тех частей, которые вам нужны:

grep -o -e '[^=,]\+=[^,]\+' file.txt |awk -F'=' '{print $1}' |sort |uniq |tr '\n' ',' |sed 's/,$/\n/'
>>> abc.xyz:1:1,k1,k2,k3,k4,STREET:1:1

(sort здесь необходимо, потому что иначе uniq не работает)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...