AWK фильтрует первую и последнюю строку заданной переменной, отбрасывает средние строки - PullRequest
0 голосов
/ 22 апреля 2019

Я пытаюсь отфильтровать файл, выбрав первую и последнюю строку заданной переменной в текстовом файле с разделителями табуляции с помощью AWK.

Файл с разделителями табуляции выглядит следующим образом:

1 apple  30
2 apple  35
3 apple  36
4 apple  20
5 pear   10
6 pear   30
7 pear   45
8 orange 16 

END 

и я пытаюсь обработать это с помощью awk, чтобы печатать только первые и последние строки каждой переменной в $ 2 (столбец с фруктами в этом примере)

Файл, который у меня есть, имеет длину ~ 35000 строк и содержит 3000 уникальных переменных в столбце, который я хочу использовать в качестве фильтра (поэтому в приведенном выше примере col2)

Я думал, что подход будет заключаться в создании массива уникальных значений col2 (яблоко, груша, апельсин), а затем с помощью этого массива извлечь первые и последние значения из файла большего размера ... но некоторые советуют по номенклатуре необходимо выбрать первую и последнюю строку для каждой индексированной переменной будет принята с благодарностью. :)

Файл INPUT, указанный выше, ожидаемый результат будет

1 apple  30
4 apple  20
5 pear   10
7 pear   45
8 orange 16

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

Ответы [ 3 ]

0 голосов
/ 22 апреля 2019

Это будет работать, даже если одни и те же данные отображаются как в первой, так и в последней строке для данного значения ключа, или если данные содержали пустые или 0 строки (при условии, что вы хотите, чтобы те обрабатывались так же, как и любая другая строка, легко пропущено, если нет):

$ cat tst.awk
$2 != prev2 {
    if ( NR > 1 ) {
        print rec
    }
    beg = rec = $0
    prev2 = $2
    next
}
{ rec = beg ORS $0 }
END { print rec }

$ awk -f tst.awk file
1 apple  30
4 apple  20
5 pear   10
7 pear   45
8 orange 16
0 голосов
/ 23 апреля 2019

попробовал на gnu awk, внешняя программа не нужна

awk '{if($0~/^[a-z0-9]/) a[NR]=$0} END{f=1;asort(a); for(;i++<NR;){split(a[i],b);if(b[2]==$2||f){$1=b[1];$2=b[2];$3=b[3];if(f){f=0;print}} else if(b[2]){print;print b[1],($2=b[2]),b[3]}} }' d
0 голосов
/ 22 апреля 2019

В одну сторону:

awk '$2!=prev{if (pline){print pline;}print;}{prev=$2;pline=$0;}END{print pline;}' file | uniq

Печатать каждый раз, когда встречается новая строка 2-го столбца. При печати новой строки 2-го столбца, если предыдущая строка не пуста, распечатайте ее также. uniq - удалить дубликаты строк, которые печатаются в случае наличия единственной записи между ними.

...