LookupCSV

Parses a CSV and looks for a specific value in a specific column, returning a dict of the entire matching row. If no column value is specified, the entire CSV is read into the context.

python · Common Scripts

Source

"""
Given a CSV file in the War Room by entry ID, searches based on column and value.
If the column is not present, simply parse the CSV into a list of lists or list of dicts (if header row supplied).
"""

import csv

from CommonServerPython import *


def search_dicts(k, v, data):
    """
    Search a list of dicts by key
    """
    match = []
    for row in data:
        if k in row and v == row[k]:
            match.append(row)

    if len(match) == 1:
        # If we only get one result: return just it as a dictr
        return match[0]
    else:
        return match


def search_lists(k, v, data):
    """
    Search a list of lists by index
    """
    match = []

    k = int(k)
    for row in data:
        row_values = list(row.values())
        if row_values[k] == v:
            match.append(row)

    if len(match) == 1:
        # If we only get one result: return just it.
        return match[0]
    else:
        return match


def main():
    d_args = demisto.args()

    entry_id = d_args.get("entryID")
    header_row = d_args.get("header_row")
    search_column = d_args.get("column")

    search_value = d_args.get("value")

    add_row = d_args.get("add_header_row")

    res = demisto.getFilePath(entry_id)
    if not res:
        return_error(f"Entry {entry_id} not found")

    file_path = res["path"]
    file_name = res["name"]
    if not file_name.lower().endswith(".csv"):
        return_error(
            f'"{file_name}" is not in csv format. Please ensure the file is in correct format and has a ".csv" extension'
        )

    csv_data: list = []
    with open(file_path) as csv_file:
        if header_row:
            csv_reader = csv.DictReader(csv_file)
            for line in csv_reader:
                csv_data.append(line)
        elif add_row:
            headers = add_row.split(",")
            csv_reader = csv.DictReader(csv_file, fieldnames=headers)
            for line in csv_reader:
                csv_data.append(line)
                if len(line) != len(add_row.split(",")):
                    return_error("Added row via add_header_row has invalid length.")

        else:
            csv_reader = csv.DictReader(csv_file, fieldnames=[])
            for line in csv_reader:
                line_values = list(line.values())

                if line_values:
                    csv_data.append(line_values[0])

    # If we're searching the CSV
    if search_column:
        if header_row:
            csv_data = search_dicts(search_column, search_value, csv_data)
        else:
            # Lists are 0-indexed but this makes it more human readable (column 0 is column 1)
            try:
                search_column = int(search_column) - 1
            except ValueError:
                return_error(f"CSV column spec must be integer if header_row not supplied (got {search_column})")
            csv_data = search_lists(search_column, search_value, csv_data)

    output = {
        "LookupCSV": {
            "FoundResult": bool(csv_data and search_column),
            "Result": csv_data if csv_data else None,
            "SearchValue": search_value if search_value else "",
        }
    }

    demisto.results({"Type": entryTypes["note"], "ContentsFormat": formats["json"], "Contents": csv_data, "EntryContext": output})


if __name__ in ("__builtin__", "builtins"):
    main()

README

Parses a CSV and looks for a specific value in a specific column, returning a dict of the entire matching row. If no column value is specified, the entire CSV is read into the context.

Script Data


Name Description
Script Type python3
Tags file, csv, Utility
Cortex XSOAR Version 5.0.0

Inputs


Argument Name Description
entryID EntryID of CSV file.
header_row CSV file has a header row.
column Column to search for value in, if not specified, entire CSV is parsed into the context.
value value to search for
add_header_row Extra row, in CSV format, to function as header if original does not contain headers

Outputs


Path Description Type
LookupCSV.Result List of result objects; either a list of dicts (with header_row) or a list of lists (no header row) Unknown
LookupCSV.FoundResult Boolean, for whether the result was found in the CSV or not. Unknown
LookupCSV.SearchValue The value that was searched. Unknown