【问题标题】:Bash Shell Programming Store Variables from Text File into ArraysBash Shell 编程将文本文件中的变量存储到数组中
【发布时间】:2012-01-25 13:42:30
【问题描述】:

我的程序应该可以这样工作。

以下是名为 BookDB.txt 的文本文件的内容 个人用冒号(:)分隔,文本文件中的每一行都应作为一组信息,并按如下所述的顺序排列。

标题:作者:价格:QtyAvailable:QtySold

Harry Potter - The Half Blood Prince:J.K Rowling:40.30:10:50
The little Red Riding Hood:Dan Lin:40.80:20:10
Harry Potter - The Phoniex:J.K Rowling:50.00:30:20
Harry Potter - The Deathly Hollow:Dan Lin:55.00:33:790
Little Prince:The Prince:15.00:188:9
Lord of The Ring:Johnny Dept:56.80:100:38

我实际上打算 1)逐行读取文件并将其存储在数组中 2) 显示它

但是我什至不知道如何开始第一个。 从网上研究,下面是我写到现在的代码。

#!/bin/bash

function fnReadFile()
{
while read inputline
do
 bTitle="$(echo $inputline | cut -d: -f1)"
 bAuthor="$(echo $inputline | cut -d: -f2)"
 bPrice="$(echo $inputline | cut -d: -f3)"
 bQtyAvail="$(echo $inputline | cut -d: -f4)"
 bQtySold="$(echo $inputline | cut -d: -f5)"
 bookArray[Count]=('$bTitle', '$bAuthor', '$bPrice', '$bQtyAvail', '$bQtySold')
Count = Count + 1
done
}

function fnInventorySummaryReport()
{
fnReadFile
echo "Title                  Author           Price          Qty Avail.      Qty Sold      Total Sales"
for t in "${bookArray[@]}"
do
echo $t
done
echo "Done!"
}

if ! [ -f BookDB.txt ] ; then #check existance of bookdb file, create the file if not exist else continue
touch BookDB.txt
fi

"HERE IT WILL THEN BE THE MENU AND CALLING OF THE FUNCTION"

感谢那些提前提供帮助的人!

【问题讨论】:

  • 我刚刚发布的这段代码有错误。
  • 什么错误?如果您将它们添加到问题中,我们将更容易为您提供帮助。
  • 第 12 行:bookArray[Count]:无法将列表分配给数组成员
  • 这一行出现错误 > bookArray[Count]=('$bTitle', '$bAuthor', '$bPrice', '$bQtyAvail', '$bQtySold')
  • bash 没有多维数组。如果这是您真正想要的,请使用具有更灵活数据结构的语言,例如 Perl。

标签: linux arrays shell unix ubuntu


【解决方案1】:

为什么要将整个内容读入数组?需要信息时查询文件:

#!/bin/sh # 未经测试的代码: # 打印与 $1 中给出的模式匹配的任何行的值 grep "$1" BookDB.txt | 而 IFS=: 阅读 Title Author Price QtyAvailable QtySold;做 回声标题= $标题 回声作者 = $Author 完毕

除非您的文本文件非常大,否则您不太可能需要数组中的数据。如果它足够大以至于您出于性能原因需要它,那么您真的不应该在 sh 中编码。

【讨论】:

  • 这就是我要做的。您不能将表格读入数组,只能读取一行,因此从文件中一次提取一行才有意义......此时您也可以直接处理它。不过,顺便说一句,您可能需要一个 while IFS=: read ... ; do ... done < <(grep ...) 构造,因此 while 中的变量是脚本其余部分的一部分。
  • 这是我第一次为它编写程序。所以请原谅我,上面的代码块,我应该用哪一部分替换?我还需要剪切功能吗?
  • @Andres 你根本不需要剪辑。将 read 与 IFS=: 一起使用是否对您有用。
  • @sorpigal 进程替换是一种有时很方便的 bashism,但应该让 OP 意识到它不可移植。 (可移植性通常不会成为问题,直到之后您已经编写了数万行代码并发现自己正在调试它们以用于 bashisms!)
  • @WilliamPursell:问题是针对 Linux,因此是 bash。
【解决方案2】:

既然您的目标似乎很明确,那么使用awk 来替代使用bash 数组怎么样?通常使用正确的工具来完成工作会使事情变得容易得多!

下面的awk 脚本应该可以得到你想要的东西:

# This will print your headers, formatted the way you had above, but without
# the need for explicit spaces.
BEGIN {
    printf "%-22s %-16s %-14s %-15s %-13s %s\n", "Title", "Author", "Price",
    "Qty Avail.", "Qty Sold", "Total Sales"
}

# This is described below, and runs for every record (line) of input
{
    printf "%-22s %-16s %-14.2f %-15d %-13d %0.2f\n",
    substr($1, 1, 22), substr($2, 1, 16), $3, $4, $5, ($3 * $5)
}

代码的第二部分(大括号之间)针对每一行输入运行。 printf 用于格式化输出,并使用给定的格式字符串打印出每个字段,用$1$2 等表示。在awk 中,这些变量用于访问记录的字段(行, 在这种情况下)。 substr() 用于截断输出,如下所示,但如果您不介意字段不对齐,可以轻松删除。我假设“总销售额”应该是价格乘以售出数量,但您也可以轻松更新。

然后,将此文件保存在books.awk 中调用此脚本,如下所示:

$ awk -F: -f books.awk books
Title                  Author           Price          Qty Avail.      Qty Sold      Total Sales
Harry Potter - The Hal J.K Rowling      40.30          10              50            2015.00
The little Red Riding  Dan Lin          40.80          20              10            408.00
Harry Potter - The Pho J.K Rowling      50.00          30              20            1000.00
Harry Potter - The Dea Dan Lin          55.00          33              790           43450.00
Little Prince          The Prince       15.00          188             9             135.00
Lord of The Ring       Johnny Dept      56.80          100             38            2158.40

-F: 告诉 awk 字段用冒号 (:) 分隔,-f books.awk 告诉 awk 要运行什么脚本。您的数据保存在books

不完全是您所要求的,而只是为您指明(IMO)这种工作的更好工具! awk 起初可能会令人生畏,但对于像这样处理唱片的工作来说,这真是太棒了!

【讨论】:

  • 嗨 Dan Fego,我真的需要用您上面提到的代码替换我的任何代码吗?对不起,这是我第一次,我很陌生,不习惯shell prog的语法。
  • 嗨 Dan Fego,显然我已经尝试过使用我的代码。但它仍然出现了错误。
  • 显然我已经尝试过使用我的代码。但它仍然出现了错误。我将您的代码合并到我的功能中,如果用户从菜单中输入选择,该功能应该被激活。下面将是我的函数function(my function) { BEGIN { printf "%-22s %-16s %-14s %-15s %-13s %s\n", "Title", "Author", "Price", "Qty Avail.", "Qty Sold", "Total Sales" } { printf "%-22s %-16s %-14.2f %-15d %-13d %0.2f\n", substring=${$1:1:22}, substring{$2:1:16}, $3, $4, $5, {$3 * $5} } awk -F: -f BookDB.awk BookDB.txt },当我尝试运行它时,它说替换错误。
  • (上述。)错误说明:在这部分代码中替换错误。 >> 子串=${$1:1:22}
  • @Andres 第一个代码块的整个文本可以保存到books.awk,然后您可以像在第二个代码块(awk -F: -f books.awk books)中一样从命令行运行它。它是您当前代码的替代品。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-27
  • 1970-01-01
相关资源
最近更新 更多