
Я хотел бы удалить несколько строк из 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, но не уверен, смогу ли создать переменную, которая будет передаваться между обработками записей.
EDIT: это было скрыто в разделе комментариев (от меня):
Я только что узнал, что переменные можно использовать между записями. Что-то, что работает не совсем так, как C. Я удалю этот вопрос, если только кто-то не даст ответ, который я посчитаю пригодным для использования другими, или кто-то не попросит меня дать ответ.
решение1
Так как он помечен тегом 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
решение2
Использование 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
решение3
Использование скрипта 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