【问题标题】:Linux bash script to add data to database将数据添加到数据库的 Linux bash 脚本
【发布时间】:2016-10-09 03:05:27
【问题描述】:

我正在尝试编写一个 bash 脚本,该脚本将从 csv 文件中提取数据并将其以我可以将其放入数据库的格式放入。 csv 文件有大约 1000 行和 8 列。当我使用命令行时,我可以得到我想要的格式的数据。我正在使用最新版本的 CentOS 最小安装。

(编辑)csv 文件的示例是:

[root@node72 ~]# cat users72.csv | head

msza907,Matyas Szabo,男子,击剑,FE,德国

krut825,Kristian Ruth,男性,帆船,SA,挪威

sdon251,Samuil Donkov,男性,射击,SH,保加利亚

aroa777,Andres Roa,男子,足球,FB,哥伦比亚

我在 CLI 中使用的代码是:

# cat users72.csv | awk -F',' '{ print "INSERT INTO athletes (id, username, gender, sport_abbreviation) VALUES (""\""$1"\""", ""\""$3"\""", ""\""$5"\""");"}'

输出示例如下所示:

INSERT INTO 运动员(id、用户名、性别、运动缩写)VALUES(“gjan887”、“Men”、“AR”);

INSERT INTO 运动员(id、用户名、性别、运动缩写)VALUES(“ifet740”、“Women”、“VO”);

INSERT INTO 运动员(id、用户名、性别、运动缩写)VALUES(“apet755”、“Men”、“AT”);

INSERT INTO 运动员(id、用户名、性别、运动缩写)VALUES(“fnep723”、“Men”、“SH”);

INSERT INTO 运动员(id、用户名、性别、sport_abbreviation)值(“othi288”、“Women”、“BK”);

这种语法对于 mysql 来说并不完全正确,因为我需要一个我使用脚本的 ID 号。 id 号必须以奇数递增,例如 1、3、5 等。我的脚本的问题是,当我运行它并将其保存到我计划用于将数据导入数据库的文件中时,它会打印一行带有 id 和用户名的行,然后下一行包含我不需要的其他数据并且我能猜出来。

下面是我的脚本:

#!/bin/bash
inputData=$(cat /root/users72.csv);
((id=1))
for athleteTable in $inputData
do
    echo "$athleteTable" | awk -F',' '{ print "INSERT INTO athletes (id, username, gender, sport_abbreviation) VALUES ('$id', " "\""$1"\"" ", " "\""$3"\"" ", " "\""$5"\""");"}'
    ((id=id+2))
done > /root/users72.sql

users72.sql 文件的示例如下所示:

INSERT INTO 运动员(id、用户名、性别、运动缩写)VALUES (1, "msza907", "", "");

INSERT INTO 运动员(id、用户名、性别、运动缩写)VALUES(3、“Szabo”、“Fencing”、“germany”);

INSERT INTO 运动员(id、用户名、性别、运动缩写)VALUES (5, "krut825", "", "");

INSERT INTO 运动员(id、用户名、性别、运动缩写)VALUES(7、“Ruth”、“Sailing”、“norway”);

INSERT INTO 运动员(id、用户名、性别、运动缩写)VALUES (9, "sdon251", "", "");

插入运动员(id、用户名、性别、运动缩写)值(11、“Donkov”、“Shooting”、“bulgaria”);

在过去的 7 个小时里,我一直在努力尝试让它工作,更改语法并查看其他示例,我开始认为操作系统存在故障。如果有人知道出了什么问题或知道完成此任务的更简单方法可以帮助我,我会很高兴。提前谢谢你。

【问题讨论】:

  • 只是说:并非所有事情都应该使用“最低级别”的编程工具(又名 shell 脚本)来完成。您会看到,解析 CSV 不仅仅是围绕“,”字符串进行拆分。根据您的数据的来源,您获取 CSV 数据的简单方法可能很快就会失败。我个人的建议:使用你最熟悉的那种“真正的”语言(java、python、c++);找到一个好的 CSV 解析器库......并编写一个“真正的程序”来做到这一点。
  • 感谢您的建议,但不幸的是,此任务的要求之一是仅使用 bash 脚本。我很想使用 python 或 ruby​​,这肯定会让我的生活更轻松,但这是不允许的。
  • 然后我看到三个选项:A) 希望有人过来帮助解决这个问题;-) B) 仍然在 python 中编写东西并使用该 bash 脚本来调用幕后的那个python脚本(嘿,无论如何调用awk和python有什么区别)C)与给你这个奇怪要求的人交谈。你看,除非这是出于教育目的,否则当手头的任务是在墙上拧螺丝时,“使用锤子”确实是错误的方法。如果您是负责实施的工程师:大声说出来
  • 您需要从输入的 CSV 文件中显示一些示例数据!
  • 嗯,这确实是为了教育目的,所以我真的无法摆脱它,相信我我试过了。

标签: linux bash awk scripting mariadb


【解决方案1】:

我肯定同意@GhostCat 的观点,解析 CSV 比仅用逗号分割要复杂得多,尽管一些琐碎的 CSV 可能会起作用。但是,CSV 通常可以在字段中包含逗号,因此以逗号分隔会破坏事情。

也就是说,您的问题是为什么脚本没有按照您的意愿进行操作,您让文件内容发生分词并尝试 awk 每个“单词”。您应该只增加 awk 内的计数器并让它为您处理读取文件。假设您对原始的 awk 命令感到满意,您可以这样做:

 awk -F',' 'BEGIN {id=1} {print "INSERT INTO athletes (id, username, gender, sport_abbreviation) VALUES ( " id " \47"$1"\47, \47"$3"\47, \47"$5"\47);";id+=2}' users72.csv

我们在这里创建一个本地 id 变量并为每行增加 2。我还使用八进制转义在每个字段周围打印单引号,而不是像您一直在做的那样使用大量引号和转义。如果您愿意,请随时返回您的方式(或者如果您想要这些,请使用\42 进行双引号)。最后,我将其更改为 awk 只是打开文件本身,我们可以避免 cat 和管道。

【讨论】:

    【解决方案2】:

    这样说会简单很多

    LOAD DATA INFILE 'users72.csv'
        INTO TABLE athletes
        FIELDS TERMINATED BY ','
        ...
        (id, username, gender, sport_abbreviation)
        ;
    

    不需要awk;快多了;等等

    Reference

    附录

    如果您不需要所有列,...

    计划 A:LOAD 到 tmp 表中,然后 INSERT SELECT 将您想要的复制到真实表中。

    B 计划:LOAD 将不需要的列放入@variables(您将无所事事)。

    【讨论】:

    • 问题是我只需要特定字段而不是 users72.csv 文件的所有列。
    • 我添加了两条关于如何做到这一点的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-22
    • 2019-05-23
    • 2019-06-30
    • 2023-04-04
    • 2013-02-03
    • 2015-07-29
    • 1970-01-01
    相关资源
    最近更新 更多