在 shell 脚本中从文本文件的数组中分配带有空格的行

问题描述 投票:0回答:1

我对 shell 脚本非常陌生,并且正在尽我最大的努力来掌握这种语言。我正在尝试将文本文件中可用的每一行分配给一个数组

例如,我有一个如下的文本文件。 enter image description here

我想将每一行分配给一个数组,如下所示。

预期输出:

Array[0]="delectus aut autem"
Array[1]="quis ut nam facilis et officia qui"
Array[2]="fugiat veniam minus"

但是,在执行下面的代码时,我们观察到数组中的每个元素都是根据每行中的空间分配的

Shell 脚本:

#!/bin/sh

cmd=$(curl  https://jsonplaceholder.typicode.com/todos)


echo $cmd > Data.json

echo $(jq '.[] | .title' Data.json) > title.txt

echo "text file creation done!"

filename=title.txt
declare -a myArray
myArray=(`cat "$filename"`)

printf '%s\n' "${myArray[@]}"

for (( i = 0 ; i < 20 ; i++))
do
  echo "Element [$i]: ${myArray[$i]}"
done

电流输出:

enter image description here

有人可以解释一下吗?

arrays shell sh element
1个回答
0
投票

您最大的问题是使用 POSIX shell 解释器行

#!/bin/sh
。 POSIX shell 不支持数组。您需要使用像
bash
这样的高级 shell,它提供 indexed
declare -a
数组和 associative
declare -A
数组。鉴于您使用
declare -a
,看来您打算使用
bash

您更幸运,

bash
提供了
mapfile
(与
readarray
同义)内置命令,可以将文件逐行读取到索引数组的元素中。您可以使用
mapfile
readarray
,它们是相同的命令,只是彼此的别名。

然后,当您想要循环数组时,请使用参数扩展

${#myArray[@]}
返回数组中的元素数量,而不是硬编码
20
或其他数字。

不必要时不要使用

cat ...
来传递信息。这称为 UUOc不必要使用
cat
,也称为 无用使用
cat
)。请参阅猫的无用使用。而是使用
>
<
重定向到文件/从文件重定向。

始终将脚本粘贴到 ShellCheck 中以查找任何问题(在此处发布之前也是个好主意)

总而言之,您可以按如下方式修改脚本。这不是唯一的方法,但却是一种合理的方法:

#!/bin/bash

## assign filenames from 1st two command-line arguments
#  use Data.json and title.txt by default if no arguments given
websrc="${1:-Data.json}"
txtfile="${2:-title.txt}"

## use redirection to save the curl data to Data.json
curl https://jsonplaceholder.typicode.com/todos > "$websrc"

## use redirection to save jq output to title.txt
jq '.[] | .title' "$websrc" > "$txtfile"

## optional output, but make information useful
#  check "%txtfile" exists and is non-empty
if [ -s "$txtfile" ]; then
  printf "text file creation done!\n"
else  # otherwise handle the error and exit with error code 1
  printf "error: failed to create txtfile '%s'\n" "$txtfile" >&2
  exit 1
fi

## declare indexed array
declare -a myArray

## read the $txtfile into array 
mapfile -t myArray < "$txtfile"

## no need to duplicate output
# printf '%s\n' "${myArray[@]}"

## use array to determine number of elements (200 in test)
for (( i = 0 ; i < ${#myArray[@]}; i++))
do
  printf "Element [%d]: %s\n" "$i" "${myArray[$i]}"
done

示例使用/输出

由于您提供了 URL,因此脚本的输出为:

$ bash curl-json-mapfile.sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 24311    0 24311    0     0   136k      0 --:--:-- --:--:-- --:--:--  137k
text file creation done!
Element [0]: "delectus aut autem"
Element [1]: "quis ut nam facilis et officia qui"
Element [2]: "fugiat veniam minus"
Element [3]: "et porro tempora"
Element [4]: "laboriosam mollitia et enim quasi adipisci quia provident illum"
Element [5]: "qui ullam ratione quibusdam voluptatem quia omnis"
Element [6]: "illo expedita consequatur quia in"
Element [7]: "quo adipisci enim quam ut ab"
Element [8]: "molestiae perspiciatis ipsa"
Element [9]: "illo est ratione doloremque quia maiores aut"
Element [10]: "vero rerum temporibus dolor"
...
Element [195]: "consequuntur aut ut fugit similique"
Element [196]: "dignissimos quo nobis earum saepe"
Element [197]: "quis eius est sint explicabo"
Element [198]: "numquam repellendus a magnam"
Element [199]: "ipsam aperiam voluptates qui"

所有 200 个元素成功存储在数组中,并且比使用

read -r
循环要容易得多(这是另一个有效选项)

仔细检查一下,如果有疑问请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.