【问题标题】:Unix: extracting data from a .dat file and inserting into SQL database?Unix:从 .dat 文件中提取数据并插入 SQL 数据库?
【发布时间】:2016-04-20 17:56:14
【问题描述】:

您好,我需要处理大约 1000 个 .dat 文件,每个文件包含大约 1000 个用户的数据。文件格式如下(实际上数据当然是填写:John, 18, john@email.com,我只是为了突出排序问题给他们编号):

<Name> Name_1
<Age> Age_1 
<Email> Email_1

<Name> Name_2
<Age> Age_2
<Email> Email_2

(...etc...)

假设我有一个数据库表,有两个列(姓名和电子邮件),我提取数据并使用 Unix/Shell/Bash 填充数据库的最佳方法是什么?目前我正在使用以下方法来尝试提取数据:

for file in $1/*;
do
    grep "<Name>" $file |
    sed 's/<Name>//g' >> temp.txt

    grep "<Email>" $file |
    sed 's/<Email>//g'>> temp.txt
done

虽然这提取了正确的数据,但输出如下:

(--File 1--)
Name_1
Name_2
Email_1
Email_2
(--File 2--)
Name_1001
Name_1002
Email_1001
Email_1002
(etc)

实际上,我认为如果可以按此顺序提取数据会更好,尽管我不知道是否可以使用 grep。

Name_1
Email_1

Name_2
Email_2

(etc)

如果数据是这样提取的,那么我可以将值存储在 shell 变量中,然后使用以下内容添加到数据库中:

sqlite db.sql INSERT INTO users VALUES ($name, $email);

或者类似的东西,如果这可行的话。

无论如何,希望我已经半清楚地解释了自己,但如果有人可以帮助我解决这个问题,我将不胜感激。实际上,我在问是否可以通过提取所有用户,然后是所有电子邮件来 grep 一个用户,然后是一封电子邮件,然后是另一个用户和相应的电子邮件......而不是 grep 似乎如何工作。也许还有另一个功能可以很好地完成这项工作?

干杯!

【问题讨论】:

  • 您的数据实际上是否包含_1、_2 等? John_1, 21_1, John@email_1 ----- Doe_2, 22_2,Doe@email_2.?
  • 不,它是完全随机的,就像你提到的 john@email.com。我会指定的。我只用数字来显示顺序...
  • 我猜到了,但想确定一下。
  • 哈哈不用担心。可惜我不能投票给你...猜我的帐户声誉太低或其他什么:(
  • 正如其他人所回答的那样,awk 可能是一个不错的选择;像它们一样输出插入语句很好,但您可能还需要考虑以 CSV 格式输出,因为“从 csv 导入”通常是将数据导入数据库的一种简单方法。另一种可能性是将perl 与数据库连接模块一起使用,在文件处理期间实际进行插入。

标签: bash shell unix grep extract


【解决方案1】:

这对grepsed 来说不是一个好问题。我推荐awk。一个未经测试的初剪:

awk '
/<Name>/ {name=$1}
/<Email>/ {emails[name] = $1}

END {for (n in emails) {print n, print email[n]}}
' *.dat

你也可以试试

END {for (n in emails) {print "sqlite db.sql INSERT INTO users VALUES (" n "," email");"}}

【讨论】:

    【解决方案2】:

    看来您是grep 的忠实粉丝。试试看:

    grep -Po '(?<=(Name|mail)>[\t\s])(.*)$' file | `xargs -n2 printf "sqlite db.sql INSERT INTO users VALUES (%s, %s)\n"`
    

    第一部分是进行积极的回顾以获取相关信息。 Lookbehind 不支持可变长度,这就是为什么使用mail 而不是Email。它输出:

    Name_1
    Email_1
    Name_2
    Email_2
    

    xargs -n2 将姓名和电子邮件组合如下:

    Name_1 Email_1
    Name_2 Email_2
    

    这是由printf 格式化并正在执行。希望对您有所帮助。

    现在请不要告诉我你的 grep 不支持 -P ;-)

    【讨论】:

      【解决方案3】:

      您可以在 (GNU) sed 中执行此操作,尽管 awk 脚本要简单得多。

      dat2sql.sed:

      /<NAME>/I H  # store name
      /<EMAIL>/I {
        H;         # store email
        g          # get stored strings
      
        s/<[^>]+>\s+//gI; # remove <NAME> and <EMAIL>
      
        s/^$\n/sqlite db.sql INSERT INTO users VALUES ("/;
        s/\n/", "/;
        s/$/" );/;
      
        p                 # print results
        s/.*//g;  x;      # clear hold space
      } 
      

      像这样使用它:sed -rn -f dat2sql.sed your_file

      前提是文件中每条记录的名称都在电子邮件之前。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-30
        • 2019-05-15
        • 2019-01-09
        相关资源
        最近更新 更多