3
  • Sample Data: Tab separated tsv file
a.1.58  fadado/CSV  https://github.com/fadado/CSV
a.1.63  jehiah/json2csv https://github.com/jehiah/json2csv
a.1.80  stedolan/jq https://github.com/stedolan/jq/issues/370
  • Following selects one record using fzf, and stores 2nd and 3rd column to an array Link:
mapfile -d $'\t' -t Link < <(awk 'BEGIN{FS="\t"; OFS="\t"} {print $2,$3}' "${SessionP}" | fzf)

Issue

In the above command I have used -t option of mapfile, but echo "${Link[1]}" prints a trailing new line!

Why is it not getting eliminated?


Reference

Porcupine
  • 1,680
  • 2
  • 19
  • 45

2 Answers2

10

Check your local documentation instead of the documentation found someplace else on the web. In an interactive bash shell session, type help mapfile, or look up he documentation for mapfile in the bash manual (man bash). Depending on your version of bash, the documentation may vary from what's found on the web.

On my system, with bash 5.1.8, help mapfile documents the -t option to mapfile like this:

-t Remove a trailing DELIM from each line read (default newline)

The DELIM is set with -d:

-d delim Use DELIM to terminate lines, instead of newline

This means that when using -d $'\t' -t with mapfile, it would remove a trailing tab character, if there was one, not a trailing newline character.

The bash shell has had mapfile -d since release 4.4. The introduction of this option was documented like this:

The mapfile builtin now has a -d option to use an arbitrary character as the record delimiter, and a -t option to strip the delimiter as supplied with -d.

To remove the trailing newline from your data when printing the last element, use "${Link[1]%$'\n'}" when outputting the element. This removes the last newline from the element if the last character is a newline character.

Kusalananda
  • 320,670
  • 36
  • 633
  • 936
2

If the input data (after awk and fzf) is something like

fadado/CSV<tab>https://github.com/fadado/CSV<nl>

and you want those two fields separately, then mapfile isn't necessarily even the best tool. Instead, you could use read -a to read to an array, or read with two variable names:

This would read the two fields to ${arr[0]} and ${arr[1]}

IFS=$'\t' read -r -a arr < ...

or

IFS=$'\t' read -r x y < ...

E.g. (skipping the process substitution for the sake of the example):

IFS=$'\t' read -r -a arr <<< $'fadado/CSV\thttps://github.com/fadado/CSV\n'
printf "'%s' '%s'\n" "${arr[0]}" "${arr[1]}"

prints

'fadado/CSV' 'https://github.com/fadado/CSV'
ilkkachu
  • 133,243
  • 15
  • 236
  • 397