【问题标题】:Creating an AWK For Loop out of piped commands使用管道命令创建 AWK For 循环
【发布时间】:2015-06-24 03:25:24
【问题描述】:

以下命令完全符合我的需要 它检查列中是否存在字符串,如果不存在则添加逗号。

awk -F, -v OFS=, '!/Reading Comprehension/ { $5 = $5 "," } 1' somefile.csv \
| awk -F, -v OFS=, '!/Sentence Skills/ { $6 = $6 "," } 1' \
| awk -F, -v OFS=, '!/Arithmetic/ { $7 = $7 "," } 1' \
| awk -F, -v OFS=, '!/College Level Math/ { $8 = $8 "," } 1' \
| awk -F, -v OFS=, '!/Elementary Algebra/ { $9 = $9 "," } 1' > endfile.csv

如何使用这个串联/管道命令并将其转换为 awk 循环?

我在想这样的事情:

awk -F, OFS=,
i = Reading Comprehension, Sentence Skills, Arithmetic, College Level Math, Elementary Algebra 
j = 5,6,7,8,9
{for ((i<=NF; j<=NF) '!/i/ { $j = $j "," } 1')}

示例输入:

last,first,A00XXXXXX,1888-01-01,2015-05-13,Elementary Algebra 34
last,first,A00XXXXXX,1888-01-01,2015-05-13,Reading Comprehension 97,Sentence Skills 104,College Level Math 76,Elementary Algebra 115
last,first,A00XXXXXX,1888-01-01,2015-05-13,Sentence Skills 104,Arithmetic 08,College Level Math 76,Elementary Algebra 115
last,first,A00XXXXXX,1888-01-01,2015-05-13,College Level Math 76,Elementary Algebra 115
last,first,A00XXXXXX,1888-01-01,2015-05-13,Sentence Skills 104,Elementary Algebra 115

样本输出:

last,first,A00XXXXXX,1888-01-01,2015-05-13,,,,,Elementary Algebra 34
last,first,A00XXXXXX,1888-01-01,2015-05-13,Reading Comprehension 97,Sentence Skills 104,Arithmetic 08,College Level Math 76,Elementary Algebra 115
last,first,A00XXXXXX,1888-01-01,2015-05-13,,Sentence Skills 104,,College Level Math 76,Elementary Algebra 115
last,first,A00XXXXXX,1888-01-01,2015-05-13,,,,College Level Math 76,Elementary Algebra 115
last,first,A00XXXXXX,1888-01-01,2015-05-13,,Sentence Skills 104,,,Elementary Algebra 115

我还在学习 AWK,对如何进行 awk 循环只有部分了解。

任何帮助都将不胜感激,并且答案的解释真的很棒。

【问题讨论】:

  • 最好发布一些示例输入/所需的输出。关于代码本身,管道 awk 5 次似乎太多了。注意你可以说awk '/condition/ {do things} /condition2/ {do other things}' file
  • @fedorqui 谢谢,我也想这样做,但仍然给我留下了一个超长的命令。我试图找到最有效且最容易阅读的方法
  • 高效!= 视觉上的美丽。管道意味着一遍又一遍地遍历所有数据。再次:发布一些数据,以便我们进行进一步检查。看起来您在逗号分隔的文件中附加逗号,但不确定具体如何
  • @fedorqui 我添加了示例输入和输出,就像我提到的那样,管道命令完全符合我的需要。我只是想把它清理一下

标签: linux bash awk


【解决方案1】:

此答案假定每个类别中的第一个词是唯一的:

awk -F, -v OFS=, '
    {
        delete val                 # clear the previous values if any
        for (i=6; i<=NF; i++) {
            split($i, a, " ")
            val[a[1]] = $i         # a[1] is the first space-separated word
        }
        print $1,$2,$3,$4,$5, val["Reading"],    # null values are OK
                              val["Sentence"], 
                              val["Arithmetic"], 
                              val["College"], 
                              val["Elementary"]
    }
' input

【讨论】:

  • @glenn jackman 有点皱纹。我从中获取文件的地方,我正在解析,只需更改文件的排序方式......基本上没有顺序。知道如何按照我在问题中提到的顺序获取它们,即使最后 5 列的每一行的顺序不同?
  • 好吧,我会成为 d@mmed,你的剧本不在乎它的顺序......我希望我能吻你。
  • @moore1emu,输出顺序在print语句中定义。
【解决方案2】:

您可以执行以下操作,但由于我们正在更改每个缺失列的 NF,因此需要一些 awk 数组舞蹈。

BEGIN 
{
   FS=OFS=","
   n=split("Reading Comprehension,Sentence Skills,Arithmetic,College Level Math,Elementary Algebra",c,",")
}

{
   delete a;
   for (i=6;i<=NF;i++) {
     for (j=1;j<=n;j++) {
       if ($i ~ c[j]) a[j]=$i
     }
   }

   print $1,$2,$3,$4,$5,a[1],a[2],a[3],a[4],a[5]
}

【讨论】:

  • 我了解顶部部分和部分部分。但是你能详细说明一下IF部分和最后的打印吗?谢谢
  • 数组a 将保持列的位置。对于相关字段 i>=6,它会扫描存储在 c 中的名称,如果匹配项放在正确的位置。一旦所有字段都被使用,打印第一个静态列和数组a 元素。 a 的某些元素不会被初始化(那些是缺失的),但会被打印为空字符串,因此您将获得每行相同数量的字段。
猜你喜欢
  • 2012-03-11
  • 1970-01-01
  • 2015-08-17
  • 1970-01-01
  • 1970-01-01
  • 2021-07-25
  • 2016-10-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多