【问题标题】:How to pass filename and file content to awk如何将文件名和文件内容传递给awk
【发布时间】:2018-04-04 02:37:16
【问题描述】:

tl;博士

有谁知道如何将文件名和文件的其余内容传递给 awk?并使其遍历目录中的所有文件并将这些操作的输出附加到 1 个最终文件?

长篇大论:

我需要基于 2 个变量每周生成一个 SQL 更新文件,并且我曾经将大量内容复制粘贴到 CSV 文件中以使这个 awk 命令运行。我的设置是这样的:

一个很长的手动粘贴在一起的 CSV,第 1 行看起来像这样:

3afb6dad-352d-4c2a-b348-40fdb3c3d9a6;019f08dd-5017-43a1-b65b-c77cb90068ab

通过 CSV 运行的 AWK 命令:

cat list.csv  | awk -F\; '{print "update db01.CONTENT set locationid = \"" $1 "\" where cdbid = \"" $2 "\";";'}

我想通过自动生成该 CSV 文件来自动执行此操作,或者通过将正确的变量直接传递给脚本来更好地实现这一点。

我有几个输入文件。在我的 awk 命令中,文件的标题必须是 $1 并且是不变的。该文件本身包含可变数量的 UUID,需要为 $2

输入

我有一个名为3afb6dad-352d-4c2a-b348-40fdb3c3d9a6 的文件。该文件的内容如下所示:

019f08dd-5017-43a1-b65b-c77cb90068ab 
0479c914-6988-4038-ac74-f5b4adb123d0 
05a6b05a-dff9-4f7c-8a7e-92c8651b8cde 
05ad4a6a-e2c6-4074-adfd-0899c15a3600 
204b12af-42d8-48a0-83c6-10e02a051ed5 
20c4fb93-6ed2-4dee-87da-749b52c76d74 
27b2552a-1050-47fb-96fe-714b4231a067 
343f34be-b1cf-4cdf-8c35-344847a13837

我有另一个名为 72d799e8-ff97-4388-a498-47badd6ca7d8 的文件,其中包含以下内容:

54b0623f-b5f0-47a1-bf90-9c8cb2054676 
8056e400-b809-4e08-bf0a-d5370f3e1b44

期望的输出

我需要的是获得一个 .sql 文件,其中包含:

 update db01.CONTENT set locationid="3afb6dad-352d-4c2a-b348-40fdb3c3d9a6" where cdbid ="019f08dd-5017-43a1-b65b-c77cb90068ab"; 
update db01.CONTENT set locationid ="3afb6dad-352d-4c2a-b348-40fdb3c3d9a6" where cdbid="0479c914-6988-4038-ac74-f5b4adb123d0"; 
update db01.CONTENT set locationid ="3afb6dad-352d-4c2a-b348-40fdb3c3d9a6" where cdbid="05a6b05a-dff9-4f7c-8a7e-92c8651b8cde"; 
update db01.CONTENT set locationid ="3afb6dad-352d-4c2a-b348-40fdb3c3d9a6" where cdbid="05ad4a6a-e2c6-4074-adfd-0899c15a3600"; 
update db01.CONTENT set locationid ="3afb6dad-352d-4c2a-b348-40fdb3c3d9a6" where cdbid="204b12af-42d8-48a0-83c6-10e02a051ed5"; 
update db01.CONTENT set locationid ="3afb6dad-352d-4c2a-b348-40fdb3c3d9a6" where cdbid="20c4fb93-6ed2-4dee-87da-749b52c76d74"; 
update db01.CONTENT set locationid ="3afb6dad-352d-4c2a-b348-40fdb3c3d9a6" where cdbid="27b2552a-1050-47fb-96fe-714b4231a067"; 
update db01.CONTENT set locationid ="3afb6dad-352d-4c2a-b348-40fdb3c3d9a6" where cdbid="343f34be-b1cf-4cdf-8c35-344847a13837"; 
update db01.CONTENT set locationid ="72d799e8-ff97-4388-a498-47badd6ca7d8" where cdbid="54b0623f-b5f0-47a1-bf90-9c8cb2054676"; 
update db01.CONTENT set locationid ="72d799e8-ff97-4388-a498-47badd6ca7d8" where cdbid="8056e400-b809-4e08-bf0a-d5370f3e1b44";

我尝试了一些尝试结合的东西

for file in ./output/*;
do
  echo ${file##*/}
done

和

while IFS='' read -r line || [[ -n "$line"]];
do
  #awk stuff
done <"$1"

但我无法得到任何结果。感谢所有帮助!

【问题讨论】:

  • 欢迎来到本站!查看tour 和how-to-ask page,了解更多关于提出可以吸引高质量答案的问题的信息。您可以edit your question 包含更多信息(尽管到目前为止我当然很欣赏您的帖子的细节!)。你对 perl 或其他工具持开放态度吗?
  • 为什么要构建一个 CSV 来处理 awk?看起来您可以通过相同的方式直接生成 SQL 脚本,而无需更多的努力。

标签: bash csv awk metaprogramming


【解决方案1】:

awk 来救援!

根据您的输入/输出文件格式

$ awk '{file=FILENAME; sub(".*/", "", file);
        print "update db01.CONTENT set locationid=\"" file 
              "\" where cdbid=\"" $1 "\""}' output/*

【讨论】:

    【解决方案2】:

    使用纯 的一种解决方案:

    #!/bin/bash
    
    cd ./output
    for file in *; do
        while read -r line; do
            echo 'update db01.CONTENT set locationid="'$file'" where cdbid ="'$line'";'
        done < $file
    done
    

    输出:

    update db01.CONTENT set locationid="3afb6dad-352d-4c2a-b348-40fdb3c3d9a6" where cdbid ="019f08dd-5017-43a1-b65b-c77cb90068ab";
    update db01.CONTENT set locationid="3afb6dad-352d-4c2a-b348-40fdb3c3d9a6" where cdbid ="0479c914-6988-4038-ac74-f5b4adb123d0";
    update db01.CONTENT set locationid="3afb6dad-352d-4c2a-b348-40fdb3c3d9a6" where cdbid ="05a6b05a-dff9-4f7c-8a7e-92c8651b8cde";
    update db01.CONTENT set locationid="3afb6dad-352d-4c2a-b348-40fdb3c3d9a6" where cdbid ="05ad4a6a-e2c6-4074-adfd-0899c15a3600";
    update db01.CONTENT set locationid="3afb6dad-352d-4c2a-b348-40fdb3c3d9a6" where cdbid ="204b12af-42d8-48a0-83c6-10e02a051ed5";
    update db01.CONTENT set locationid="3afb6dad-352d-4c2a-b348-40fdb3c3d9a6" where cdbid ="20c4fb93-6ed2-4dee-87da-749b52c76d74";
    update db01.CONTENT set locationid="3afb6dad-352d-4c2a-b348-40fdb3c3d9a6" where cdbid ="27b2552a-1050-47fb-96fe-714b4231a067";
    update db01.CONTENT set locationid="3afb6dad-352d-4c2a-b348-40fdb3c3d9a6" where cdbid ="343f34be-b1cf-4cdf-8c35-344847a13837";
    update db01.CONTENT set locationid="72d799e8-ff97-4388-a498-47badd6ca7d8" where cdbid ="54b0623f-b5f0-47a1-bf90-9c8cb2054676";
    update db01.CONTENT set locationid="72d799e8-ff97-4388-a498-47badd6ca7d8" where cdbid ="8056e400-b809-4e08-bf0a-d5370f3e1b44";
    

    【讨论】:

    • 嗨,吉尔斯,感谢您的信息!当我执行此代码时,我得到一个空的 locationid=""。但是,cdbid 已正确解析。有什么想法吗?我应该用其他东西替换 $i 吗?
    【解决方案3】:

    正如我在 cmets 中所写的那样,创建一个 CSV 中间文件只是为了与 awk 一起使用是毫无意义的。如果您可以创建这样的文件,那么您也可以直接创建所需的 SQL 脚本。例如:

    #!/bin/bash
    
    for file in ./output/*;
    do
      location=$(basename "$file")
      while read cb <"$file"; do
        echo "update db01.CONTENT set locationid=\"${location}\" where cdbid =\"${cb}\";"
      done
    done
    

    该版本将结果写入标准输出。您可以将其重定向到您想要的位置,或者将所需的重定向放入脚本中。

    【讨论】:

    • 您好约翰,感谢您的帮助! csv 方法是我的旧方法。我收集了一堆 UUID 并将它们放入 csv 中。但是,我现在有另一个脚本,每 $1 为我创建一个文件,列出与 $1 匹配所需的所有变量我认为您提供的脚本仍然有问题。当我只有 1 个文件只包含一行时,脚本会不断运行,一遍又一遍地生成相同的 sql 查询,例如。文件 72d799e8-ff97-4388-a498-47badd6ca7d8 今天是唯一只包含一行的文件:54b0623f-b5f0-47a1-bf90-9c8cb2054676
    【解决方案4】:

    不是awk,而是 单行:

     perl -ne 'chomp; print "update db01.CONTENT set locationid=\"$ARGV\" where cdbid=\"$_\";\n";' * > whatever.sql
    

    测试

    我创建了一个包含以下内容的两个文件的测试目录:

    in1:(类似于3afb6dad-352d-4c2a-b348-40fdb3c3d9a6)

    out1         (analogous to 019f08dd-5017-43a1-b65b-c77cb90068ab)
    out2         (analogous to 0479c914-6988-4038-ac74-f5b4adb123d0)
    

    in2:(类似于72d799e8-ff97-4388-a498-47badd6ca7d8)

    out3         (analogous to 54b0623f-b5f0-47a1-bf90-9c8cb2054676)
    out4         (analogous to 8056e400-b809-4e08-bf0a-d5370f3e1b44)
    

    当我使用 Perl 5.22 运行上述内容时,我得到:

    update db01.CONTENT set locationid="in1" where cdbid="out1";
    update db01.CONTENT set locationid="in1" where cdbid="out2";
    update db01.CONTENT set locationid="in2" where cdbid="out3";
    update db01.CONTENT set locationid="in2" where cdbid="out4";
    

    我认为这与您想要的类似。

    说明

    编辑-n 开关在给定命令周围提供while(&lt;&gt;){ ... }。 因此,perl 处理命令行中给出的每个文件,一次一行。在脚本(隐式循环体)中,$_ 是行,$ARGV 是它来自的文件的名称 (reference)。 chomp 从$_ 中删除尾随换行符,然后print 语句输出您想要的SQL。所有输出都由 shell 保存到whatever.sql。

    【讨论】:

    • 为什么不使用-n 开关而不是while(&lt;&gt;) ?
    • @GillesQuenot 因为我没想到;)。已编辑 --- 非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-25
    • 1970-01-01
    • 1970-01-01
    • 2019-05-08
    • 1970-01-01
    • 2018-06-16
    • 2018-04-13
    相关资源
    最近更新 更多