У меня есть файл, который выглядит так:

194104,41.8,38.3
194104,46.7,39.6
194104,47.4,39.7
194104,49.8,44.3
194104,50.8,47.5
194136,39.9,36.3
194136,45.2,37.8
194170,46.9,42.2
...

Я хочу сохранить шесть первых строк, начиная с 194104, а затем удалить следующие две строки, потому что есть только две строки, начинающиеся с этого числа. И так далее для остальной части файла.

Можно ли это сделать с помощью sed/awk/grep или других инструментов Unix?

3 ответа3

0

Это, кажется, делает трюк:

perl -F, -ane '
    if ($. > 1) {
        if (@q == 6) { print @q; undef @q }
        elsif ($F[0] ne $prev) { undef @q }
    }
    push @q, $_;
    $prev = $F[0];
    END { if (@q == 6) {print @q} }
'
0

Можно ли это сделать с помощью sed/awk/grep или других инструментов Unix?

Да.

...

Это можно сделать с помощью таких инструментов, как awk или perl, примерно в 20 строках кода.

$ cat t.txt
194104,41.8,38.3
194104,46.7,39.6
194104,47.4,39.7
194104,49.8,44.3
194104,50.8,47.5
194136,39.9,36.3
194136,45.2,37.8
194170,46.9,42.2

$ perl t.pl t.txt
194104,41.8,38.3
194104,46.7,39.6
194104,47.4,39.7
194104,49.8,44.3
194104,50.8,47.5

$ wc -l t.pl
19 t.pl

Основные идеи, которые я использовал, были

  • зацикливать ввод строки одновременно
  • добавить строки в буфер
  • проверь значение первого слова
  • вести учет того, сколько раз его видели
  • если отличается, решите, следует ли печатать и очищать буфер, сбрасывать счетчик

ПСЕВДОКОД

Это соответствует строка за строкой с моим кодом perl, но perl немного лаконичнее (и я обнимаю своих остальных, хотя Ларри не одобряет).

let my minimum be 5
let my buffer be blank
let my count be zero
let my prior first word be blank

while read a line

   if there is a numeric first word followed by a comma 
   then
      if that first word was the same as my prior first word
      then
         increment my count
      otherwise
         if my count is greater than or equal to my minimum
         then
           print my buffer
         end if
         empty my buffer
         let my count be one
      end if
      let my prior first word be the one I just read
      append the line I just read to my buffer
   end if
end while

Вероятно, это может быть сделано в несколько строк или длинным однострочником.

0

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

$ cat 6lines.awk
$1 == prev {
   ++cnt
   block = block $0 RS
   if (cnt == 6) {
      printf block
      cnt = 0
      block = ""
   }
   next
}

{
   block = $0 RS
   prev = $1
   cnt = 1
}

awk -F, -f 6lines.awk ввод

Мы эксплуатируем, что awk берет все, что не назначено, как пустую строку (ранее здесь).

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .