Linux -如何从csv文件读取数据(包含多行值)并存储到数组中

xmd2e60i  于 2023-08-03  发布在  Linux
关注(0)|答案(1)|浏览(161)

我有一个测试.csv文件,内容如下:

test 123
abc 456
def 789
hello hkdsfhhif
      kjsdfkjdshfkj
      jhkjsdfhksdfhksdh
hey 218es@#$9#RDS

字符串
我写了一个shell脚本:

while IFS=' ' read -ra array; do
  column+=("${array[0]}")
  column2+=("${array[1]}")

done < test.csv
printf '%s\n' "${column[@]}" "${column2[@]}"


这背后的全部原因是- column[1]是键,column 2 [1]是其各自的值。一切都按预期工作,除了行- hello和它的多行值-hkdsfhhi。
现在我的问题是,如果数据包含多行值,如何从csv中读取数据。

snz8szmq

snz8szmq1#

首先,您的输入数据与CSV无关,它是一种任意的自定义格式,这是可以的,但是称之为CSV听起来很混乱。
第二,在一个数组中有键而在另一个数组中有值通常是令人不快的,因为这会打开一罐蠕虫(可能是不一致的状态),例如两个数组的大小不同或其他索引不匹配。
遗憾的是,Bash并没有记录/结构数据类型。因此,出于此目的,在以下假设下,最接近的近似值可以是关联数组:
1.行具有两个标记(一个键和一个值)或单个标记(前一个值的延续)。
1.空格并不重要,也不会出现在令牌内(即没有引号或转义语法)。
1.密钥是唯一的,或者最后出现的密钥可以“胜出”并覆盖以前的值。

#!/bin/bash
set -euo pipefail

parse_data() {
  local -n target_array="$1"
  local first second old_key
  target_array=()
  while read -r first second; do
    if [[ -n "$second" ]]; then
      old_key="$first"
      target_array["$first"]="$second"
    else
      target_array["$old_key"]+="$first"
    fi
  done
}

declare -A data  # associative array
parse_data data << DATA
test 123
abc 456
def 789
hello hkdsfhhif
      kjsdfkjdshfkj
      jhkjsdfhksdfhksdh
hey 218es@#$9#RDS
DATA

for key in "${!data[@]}"; do
  printf '"%s" : "%s"\n' "$key" "${data["$key"]}"
done

字符串
很明显,这个↑没有任何错误检查。因此,如果文件(例如)以多行值开头,但没有键,则会导致(关联)数组下标错误等。更不用说空行、每行超过2个令牌等。* 可能的 * 上述代码片段的输出:

"def" : "789"
"hello" : "hkdsfhhifkjsdfkjdshfkjjhkjsdfhksdfhksdh"
"hey" : "218es@##RDS"
"abc" : "456"
"test" : "123"

  • “可能”* 输出的注意事项:关联数组是在迭代过程中具有未定义键顺序的哈希Map。如果您需要保持可预测的密钥顺序,您可以请使用包含键的附加索引数组。在指向关联数组(散列Map)的(字符串)键的(整数索引)数组上进行迭代会产生可预测的键排序。

相关问题