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.
"""
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.