# CSV<no value>
// <!-- Required for asciidoctor -->
:toc:
// Set toclevels to be at least your hugo [markup.tableOfContents.endLevel] config key
:toclevels: 4

[cols="1^,1^,1^",options=header]
|===
| source | condition | target
| &#10004; | &#10004; | &#10004;
|===

== Description

The `csv` resource reads and writes a single cell in a CSV file. Rows are addressed by index and columns by header name through a link:https://daseldocs.tomwright.me/[Dasel] selector, so `.[0].firstname` is the `firstname` column of the first data row.

**source**::
Reads one cell out of one file. Only a single file is accepted.

**condition**::
Compares the cell to `value`, or to the source output when `value` is unset.

**target**::
Writes the value into the cell. Files already holding it are reported as up to date and left untouched.

== Parameters

{{< resourceparameters "sources" "csv" >}}

`file` or `files` is mandatory, as is `key` or `query`; missing either aborts the run with `wrong spec content`. `file` and `files` are mutually exclusive.

NOTE: `multiple` is deprecated and hidden from the table above. Use a selector returning several values instead.

=== Separator and comment characters

`comma` and `comment` are Go runes, not strings. They must be given as the **decimal code point** of the character, so a semicolon-separated file is `comma: 59`, not `comma: ";"`:

[source,yaml]
----
spec:
  file: data.csv
  key: .[0].version
  comma: 59      # ";" - 44 is "," (the default), 9 is a tab
----

Passing the character itself aborts the run before the pipeline starts:

[source,text]
----
error while cleaning config: failed to create resource csv: decoding failed due to the following error(s):
'Comma' expected type 'int32', got unconvertible type 'string'
----

`comment` works the same way and defaults to `#`, which is code point 35.

== Engines

`engine` selects which version of Dasel parses the file, and the selector syntax is not portable between versions.

[cols="1,3",options=header]
|===
| Value | Behaviour
| `dasel/v1` | Default when `engine` is unset. Deprecated - every run logs a warning.
| `dasel/v2` | Deprecated - every run logs a warning.
| `dasel/v3` | Current engine. Rejects the leading dot: use `[0].firstname`, not `.[0].firstname`.
| `dasel` | Alias resolving to the latest engine, currently `dasel/v3`.
|===

WARNING: `query` is a `dasel/v1` parameter. On `dasel/v2` and `dasel/v3`, a `query` without a `key` fails validation with `engine "dasel/v3" requires the parameter "key" over "query"`. On `dasel/v1`, `query` is the multi-value form and must be paired with `versionfilter` in a source.

== Remote files

`file` accepts `https://`, `http://` and `file://` for a source and a condition. A target refuses a URL outright:

[source,text]
----
URL scheme is not supported for CSV target: "https://example.com/data.csv"
----

== Limitations

Dasel rewrites the file from its parsed representation, so **comments are dropped** on any target that changes something - see link:https://github.com/TomWright/dasel/issues/178[tomwright/dasel#178]. Formatting details such as quoting style are normalised the same way.

When that matters, drive the edit with the link:/docs/plugins/resource/file/["File" resource] and a `matchpattern`/`replacepattern` pair instead, which rewrites only the bytes that changed.

== Example

[source,yaml]
----
# updatecli.yaml
{{<include "assets/code_example/docs/plugins/resources/csv/updatecli.d/default.yaml">}}
----

== Links

* link:https://daseldocs.tomwright.me/[Dasel documentation]
* link:/docs/core/versionfilter/["Version Filtering" page]
