【问题标题】:How do I detect embbeded field names and reorder fields using awk?如何使用 awk 检测嵌入的字段名称和重新排序字段?
【发布时间】:2020-07-16 00:30:32
【问题描述】:

我有以下数据:

"b":1.14105,"a":1.14106,"x":48,"t":1594771200000
"a":1.141,"b":1.14099,"x":48,"t":1594771206000
...

我试图以给定的顺序显示数据,并且只显示三个字段。由于不能保证字段顺序,我需要为每行的每个逗号分隔列读取“标签”。

我已尝试使用awk 解决此任务:

awk -F',' '
                {
                        for(i=1; i<=$NF; i++) {
                                if(index($i,"\"a\":")!=0) a=$i;
                                if(index($i,"\"b\":")!=0) b=$i;
                                if(index($i,"\"t\":")!=0) t=$i;
                        }
                        printf("%s,%s,%s\n",a,b,t);
                }
        '

但我明白了:

,,
,,
...

在上述数据样本中,我希望:

"a":1.14106,"b":1.14105,"t":1594771200000
"a":1.141,"b":1.14099,"t":1594771206000
...

注意:我使用的是 FreeBSD 附带的 awk

【问题讨论】:

  • 之前是 JSON 吗?
  • 也许这个答案可能有用:stackoverflow.com/a/59320486/8344060
  • @Cyrus 是的,它之前是 JSON(如果您有任何建议在命令行上解析 JSON 而不使用编程语言)
  • @M.E.:如果您有权访问jqperl,我建议使用有效的 JSON 文件开始一个新问题。
  • 我绝对不想使用perl 我知道如何使用PythonJava 但我试图避免通过简单的工具使用它们。如果您想帮助我将 JQ 合并到我的工具集中,这是 JQ 问题:stackoverflow.com/questions/62938833/…

标签: regex awk freebsd


【解决方案1】:
$ cat tst.awk
BEGIN {
    FS = "[,:]"
    OFS = ","
}
{
    for (i=1; i<NF; i+=2) {
        f[$i] = $(i+1)
    }
    print p("a"), p("b"), p("t")
}

function p(tag, t) {
    t = "\"" tag "\""
    return t ":" f[t]
}

.

$ awk -f tst.awk file
"a":1.14106,"b":1.14105,"t":1594771200000
"a":1.141,"b":1.14099,"t":1594771206000

【讨论】:

  • 这个答案没有我的那么难看。 +1
  • @Cyrus 我用 sed 提前删除了 '"' 字符并稍微修改了你的答案(实际上我只需要这些值),我仍然发现你的答案比这个更容易阅读 - 这意味着只是那个,我发现你的更容易阅读和关注我-
  • ME希望很明显,如果没有"s 并且仅打印值,我的答案和@Cyrus 的值会减少为数组名称以外的相同脚本(他使用a[],我使用f[])。我们的 2 个脚本之间的主要区别在于选择如何格式化输出字段 - 他为每个字段写出 "\"a\":" a["a"],我使用了一个将 "a" 转换为 "\"a\":" a["a"] 的函数,所以你可以只写 @987654329 @ 为每个字段。 " 是否被视为 FS 的另一个区别是绒毛,如果字段中没有 "s 就会消失。
【解决方案2】:

使用awk 和一个数组:

awk -F '[:,]' '{for(i=1; i<=NF; i=i+2){a[$i]=$(i+1)}; print "\"a\":" a["\"a\""] ",\"b\":" a["\"b\""] ",\"t\":" a["\"t\""]}' file

awk -F '[":,]' '{for(i=2; i<=NF; i=i+4){a[$i]=$(i+2)}; print "\"a\":" a["a"] ",\"b\":" a["b"] ",\"t\":" a["t"]}' file

输出:

"a":1.14106,"b":1.14105,"t":1594771200000 "a":1.141,"b":1.14099,"t":1594771206000

【讨论】:

    【解决方案3】:

    类似awk,您可以在其中指定字段和顺序。

    $ awk -F[:,] -v fields='"a","b","t"' 'BEGIN{n=split(fields,f)} 
                {for(i=1;i<NF;i+=2) map[$i]=$(i+1); 
                 for(i=1;i<=n;i++) printf "%s", f[i]":"map[f[i]] (i==n?ORS:",")}' file
    
    "a":1.14106,"b":1.14105,"t":1594771200000
    "a":1.141,"b":1.14099,"t":1594771206000
    

    【讨论】:

      猜你喜欢
      • 2016-10-04
      • 1970-01-01
      • 2023-03-04
      • 2021-06-08
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 2020-05-25
      相关资源
      最近更新 更多