Удалить определенные строки

Я хотел бы удалить несколько строк из CSV-файла.

Правила достаточно просты (оставьте строку, если):

  • Это первая строка в файле.
  • Первое значение отличается от первого значения предыдущего ряда.
  • Второе значение увеличилось как минимум на 10 от предыдущей сохраненной строки.

Источник

Test1,  0.0, 1
Test1,  0.2, 1
Test1, 10.0, 3
Test2,  0.1, 1
Test2,  0.3, 3
Test2,  1.0, 5
Test2, 11.0, 7

Результат

Test1,  0.0, 1
Test1, 10.0, 3
Test2,  0.1, 1
Test2, 11.0, 7

Я думал сделать это с помощью awk и нескольких операторов if, но я не уверен, что смогу сделать переменная, которая передается между обработкой записей.


РЕДАКТИРОВАТЬ: это было скрыто в разделе комментариев (от меня):

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

3
задан 24 November 2015 в 18:08

3 ответа

Так как это отмечено с awk

awk -F", *" 'x!=$1||$2>=y+10{y=$2;print}{x=$1}' file


Test1,  0.0, 1
Test1, 10.0, 3
Test2,  0.1, 1
Test2, 11.0, 7
5
ответ дан 25 November 2015 в 04:08

Использование Perl:

perl -lane 'if($.==1||"$F[0]"ne"$F0"||$F[1]>=$F1+10){print;$F1=@F[1]}$F0=@F[0]' file

Расширенный:

if($. == 1 || "$F[0]" ne "$F0" || $F[1] >= $F1 + 10){
    print;
    $F1 = @F[1]
}
$F0 = @F[0]
  • if($.==1||"$F[0]"ne"$F0"||$F[1]>=$F1+10){print;$F1=@F[1]}: если число текущей строки 1, первое поле текущей строки равно первому полю предыдущей строки, или второе поле текущей строки больше или равно второму полю предыдущей строки, печатает текущую строку и присваивает значение второго поля текущей строки к F1;
  • $F0=@F[0]: присваивает значение первого поля текущей строки к F0;
% cat file
Test1,  0.0, 1
Test1,  0.2, 1
Test1, 10.0, 3
Test2,  0.1, 1
Test2,  0.3, 3
Test2,  1.0, 5
Test2, 11.0, 7
% perl -lane 'if($.==1||"$F[0]"ne"$F0"||$F[1]>=$F1+10){print;$F1=@F[1]}$F0=@F[0]' file
Test1,  0.0, 1
Test1, 10.0, 3
Test2,  0.1, 1
Test2, 11.0, 7
0
ответ дан 25 November 2015 в 04:08

Используя сценарий Python:

#! /usr/bin/env python3
import sys
with open (sys.argv[1]) as f:
  rows=[list(map(str.strip, line.split(','))) for line in f.readlines()]
  result=rows[0:1]
  for r in rows:
    if r[0] != result[-1][0] or float(r[1]) >= float(result[-1][1])+10:
      result.append(r)
  print("\n".join([",".join(res) for res in result]))

Скопируйте сценарий выше и вставьте его в названный файл csvfilter.py например.
Сделайте это исполняемым использованием chmod +x csvfilter.py.

Затем можно выполнить его от командной строки с файлом CSV для обработки (я сохранил пример от вопроса как source.csv) как аргумент:

$ ./csvfilter.py source.csv 
Test1,0.0,1
Test1,10.0,3
Test2,0.1,1
Test2,11.0,7

Сценарий не изменит исходный файл, но просто распечатает новую версию к стандартному выводу. Кроме того, любое предыдущее форматирование с помощью пробелов будет отброшено.

Для замены исходного файла измененной версией перенаправьте вывод назад в исходный файл:

$ ./csvfilter.py source.csv > source.csv

Можно также сохранить измененную версию как файл:

$ ./csvfilter.py source.csv > modified.csv
1
ответ дан 25 November 2015 в 04:08
  • 1
    Можно сделать последнюю часть без временного файла с sudo python <(wget -O- https://bootstrap.pypa.io/get-pip.py 2>/dev/null) – Chai T. Rex 1 June 2018 в 07:10

Другие вопросы по тегам:

Похожие вопросы: