Удаление ненужных строк из CSV-файла, имеющего более 10 шаблонов для сопоставления

У меня есть CSV файл, который имеет 2 columns и я должен match значения в отдельной строке в обоих столбцах, если это соответствует критериям, мы должны сохранить столбец в противном случае delete весь ряд. Ниже приведен пример моего CSV-файла:

lidocaine (oint, patch) generic 1   tube of cream
lidocaine (oint, patch) generic 1   kit
lidocaine (oint, patch) generic 1   bottle of topical solution
lidocaine (oint, patch) generic 1   tube of ointment
lidocaine (oint, patch) generic 1   tube of ointment
lidocaine (oint, patch) generic 1   jar of ointment
lidocaine (oint, patch) generic 1   bottle of lotion
lidocaine hcl (gel 2%, soln 4%) generic 1   patch

здесь, кроме строк 4-го, 5-го и 6-го, все остальные строки будут удалены. Причина этого заключается в следующем:

  1. первый ряд имеет мазь и пятно слева, но крем справа, поэтому он будет удален.

    Аналогичным образом будут удалены 2-й и 3-й ряды.

  2. 4-й, 5-й и 6-й ряды не будут удалены, потому что они имеют мазь слева и аналогичное слово мазь справа.

Так как же это реализовать programatically так как у меня есть более 10 аналогичных условий, чтобы соответствовать, прежде чем строка будет удалена.

Пожалуйста, если кто-нибудь может мне помочь. Спасибо:)

1 ответ

Ой! опоздал на несколько лет, извините. Для полноты я добавлю ответ, связанный с bash.

Если вы не против запачкать руки регулярными выражениями, grep может стать вашим другом:

$ cat test.csv | grep -Es 'oint.*oint'                                                                     
lidocaine (oint, patch) generic 1   tube of ointment
lidocaine (oint, patch) generic 1   tube of ointment
lidocaine (oint, patch) generic 1   jar of ointment

Здесь были отобраны только ряды с чем-то "мазью" посередине и снова "мазью".

Вы можете использовать оператор регулярного выражения 'или' | и добавьте другое условие, например, чтобы после слова 'gel' следовало x%, что является числом x от 1 до 20:

$ cat test.csv | grep -Es 'oint.*oint|gel (20|1[0-9]|[1-9])%'
lidocaine (oint, patch) generic 1   tube of ointment
lidocaine (oint, patch) generic 1   tube of ointment
lidocaine (oint, patch) generic 1   jar of ointment
lidocaine hcl (gel 2%, soln 4%) generic 1   patch

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

#! /usr/bin/env python3
import sys

COLUMN_SEPARATOR = "   "  # character or string used as column separator. Tab = "\t"
SEARCH_STRING = "oint".lower()  # case-insensitive string that needs to be present in all columns

with open (sys.argv[1]) as f:
  rows=[list(map(str.strip, line.split(COLUMN_SEPARATOR))) for line in f.readlines()]
  for r in rows:
    if all([SEARCH_STRING in r[i].lower() for i in range(len(r))]):
      print(COLUMN_SEPARATOR.join(r))

Скопируйте скрипт выше и сохраните его как любой файл, например csvfilter.py,
Сделайте его исполняемым с помощью chmod +x csvfilter.py,

Затем запустите его с файлом для обработки в качестве одного аргумента.
Пример вывода с примером выше (столбцы разделены 3 пробелами) как source.csv:

$ ./csvfilter.py source.csv
lidocaine (oint, patch) generic 1   tube of ointment
lidocaine (oint, patch) generic 1   tube of ointment
lidocaine (oint, patch) generic 1   jar of ointment

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

Чтобы заменить исходный файл измененной версией, перенаправьте вывод обратно в исходный файл:

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

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

$ ./csvfilter.py source.csv > modified.csv
Другие вопросы по тегам