awk - сохранить в файле только те строки, которые начинаются с одинаковых символов в определенном столбце - PullRequest
0 голосов
/ 30 апреля 2020

У меня есть файл с примерно 1000 строками данных, который выглядит следующим образом

ZIPCODE;STREETNAME;NAME;MAIL-ADDRESS  
12345;Mainstreet 1;Anton;anton@gmail.com  
23456;First Street 3;Mike;mike@yahoo.com
12345;Mainstreet 15;Tom;tom@hotmail.com
63434;Second Street 23;Anna;anna@mail.com
23456;First Street 74;Patrick;patrick@hotmail.com
32753;Third Street 28;Alex;alex@gmail.com

В этом случае я хочу определить (и сохранить только) строки, в которых совпадают первые 6 символов названия улицы по крайней мере, еще одну строку.

Требуемый вывод должен выглядеть следующим образом (оставляя только те строки, в которых первые 6 букв столбца 2 совпадают с некоторыми другими строками)

12345;Mainstreet 1;Anton;anton@gmail.com  
23456;First Street 3;Mike;mike@yahoo.com
12345;Mainstreet 15;Tom;tom@hotmail.com (<- same street as #1)
23456;First Street 74;Patrick;patrick@hotmail.com (<- same street as #2)

Я понял, как просто сохранить строки с тем же полным названием улицы (столбец 2), используя awk

awk -F';' 'BEGIN {OFS = FS} { c[$2]++; l[$2,c[$2]]=$0 } END { for (i in c) { if (c[i] > 1) for (j = 1; j <= c[i]; j++) print l[i,j] } }' FILE

Я также знаю, что есть функция для подстрок (substr (s, index, len)) в awk, но я не могу понять, как изменить вышеупомянутый код, чтобы использовать только первые 6 букв столбца 2.

Есть идеи?

Спасибо, Патрик

Ответы [ 3 ]

0 голосов
/ 30 апреля 2020

Лог c немного запутан, но прокомментировал, что может помочь. Что вы хотите сделать, это сохранить записи в массиве, а затем сохранить количество раз, когда первая 6-символьная подстрока видна. Затем в правиле END l oop для подстрок, а для тех, чье число больше единицы, l oop печатает записи, в которых первые 6 символов поля 2 соответствуют подстроке, например,

С вашими данными в файле с именем streets вы получите:

awk -F';' '{
    recs[$2]=$0             # save records keyed by 2nd field
    ss[substr($2,1,6)]++    # save count of substr of 6 chars from 2nd field
}
END {
    for (i in ss)                           # loop saved substrings
        if (ss[i] > 1)                      # if count > 1
            for (j in recs)                 # loop stored records
                if (substr(j,1,6) == i)     # if 1st 6 chars match substring
                    print recs[j]           # print record
}' streets
23456;First Street 74;Patrick;patrick@hotmail.com
23456;First Street 3;Mike;mike@yahoo.com
12345;Mainstreet 15;Tom;tom@hotmail.com
12345;Mainstreet 1;Anton;anton@gmail.com

Дайте мне знать, если у вас есть вопросы. Похоже, @ user727089 может иметь немного более чистую логи c.

0 голосов
/ 30 апреля 2020

подход двойного сканирования будет тривиальным

$ awk -F\; '{k=substr($2,1,6)} 
     NR==FNR{a[k]++; next} 
     a[k]>1' file{,}

12345;Mainstreet 1;Anton;anton@gmail.com
23456;First Street 3;Mike;mike@yahoo.com
12345;Mainstreet 15;Tom;tom@hotmail.com
23456;First Street 74;Patrick;patrick@hotmail.com
0 голосов
/ 30 апреля 2020

То есть вы хотите отказаться от упоминания названия улицы? Измените вашу команду следующим образом:

awk -F';' '
BEGIN {OFS = FS} 
{ pfx=substr($2,1,6); c[pfx]++; l[pfx,c[pfx]]=$0 } 
END { for (i in c) { if (c[i] > 1) for (j = 1; j <= c[i]; j++) print l[i,j] } }' FILE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...