【问题标题】:Reformat data using awk使用 awk 重新格式化数据
【发布时间】:2018-06-29 17:43:53
【问题描述】:

我有一个数据集,其中包含多行 UUID,后跟位置和事务 ID。 UUID 由分号 (';') 分隔,事务由制表符分隔,如下所示:

01234;LOC_1=ABC    LOC_1=BCD    LOC_2=CDE
56789;LOC_2=DEF    LOC_3=EFG

我提前知道所有的位置代码。我想要做的是将这些数据转换为我可以加载到 SQL/Postgres 中进行分析的格式,如下所示:

01234;LOC_1=ABC
01234;LOC_1=BCD
01234;LOC_2=CDE
56789;LOC_2=DEF
56789;LOC_3=EFG

我很确定我可以使用 awk(或类似方法)轻松地做到这一点,方法是从文件(例如 LOC_1)中查找位置 ID,并匹配位置 ID 的任何实例并将其打印在 UUID 旁边。我还没有把它弄好,非常感谢任何帮助!

我的位置文件名为location,我的数据集为data。请注意,我可以编辑原始文件或将结果写入新文件,都可以。

【问题讨论】:

标签: linux awk sed grep


【解决方案1】:

awk 不使用split:使用分号制表符作为字段分隔符

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

【讨论】:

  • 是的,稳健地完成这项工作就是这么简单。
【解决方案2】:

我认为您不需要匹配已知的位置列表;您应该可以随时打印每一行:

$ awk '{print $1; split($1,a,";"); for (i=2; i<=NF; ++i) print a[1] ";" $i}' file
01234;LOC_1=ABC
01234;LOC_1=BCD
01234;LOC_2=CDE
56789;LOC_2=DEF
56789;LOC_3=EFG

【讨论】:

    【解决方案3】:

    您对了解位置和映射文件的评论让我怀疑您的示例似乎所做的并不完全是所要求的 - 但您似乎想要重新格式化每组制表符分隔 LOC=将它们的 UUID 放在一行中。

    如果是这样,这就行了:

    awk ' BEGIN {OFS=FS=";"} {split($2,locs,"\t"); for (n in locs) { print $1,locs[n]}}' 
    

    给定:

    $ cat -A data.txt
     01234;LOC_1=ABC^ILOC_1=BCD^ILOC_2=CDE$
     56789;LOC_2=DEF^ILOC_3=EFG$
    

    然后:

    $ awk ' BEGIN {OFS=FS=";"} {split($2,locs,"\t"); for (n in locs) { print $1,locs[n]}}' data.txt
     01234;LOC_1=ABC
     01234;LOC_1=BCD
     01234;LOC_2=CDE
     56789;LOC_2=DEF
     56789;LOC_3=EFG
    

    BEGIN {OFS=FS=";"} 块将输入和输出分隔符设置为 ;。

    然后,对于每一行,我们将第二个字段拆分为一个名为 locs 的数组,在制表符上拆分,通过 - split($2,locs,"\t")

    然后遍历 locs 打印 UUID 和每个 loc 值 - for (n in locs) { print $1,locs[n]}

    【讨论】:

    • 希望你不关心输出的顺序,因为这会以随机顺序打乱它。您可能很幸运并获得了您发布的示例输入的预期顺序,但这只是运气。
    • @EdMorton 像往常一样正确 =)。捕获拆分输出(例如n=split($2,locs,"\t"))并修改循环以对其进行迭代 - for (i=1;i&lt;=n;i++) { print $1,locs[i]}},如果需要,将为您提供有序的结果。
    • 老实说,有人总是对所有答案投反对票,这非常令人沮丧:(有些人必须开始学习编码并期待我们帮助或指导他们,所以我们正在尝试在这里做。我想请人(投反对票的人)从他们的角度思考,因为我们都在这里学习。无论如何我从早上得到了 4 没有提到的原因:(
    • 不是“某人”-@jww。我现在像往常一样投票支持他们来弥补。让我知道他最近还胡扯了哪些其他问题,我也会投票赞成。
    • 完成,所有引用的问答都被盲目赞成以弥补@jww 的盲目反对。
    【解决方案4】:

    如下没有循环或没有拆分一个怎么样。(考虑到 Input_file 仅与所示示例相同)

    awk 'BEGIN{FS=OFS=";"}{gsub(/[[:space:]]+/,"\n"$1 OFS)} 1'  Input_file
    

    【讨论】:

      【解决方案5】:

      这可能对你有用(GNU sed):

      sed -r 's/((.*;)\S+)\s+(\S+)/\1\n\2\3/;P;D' file
      

      用换行符重复替换位置之间的空白,然后是 UUID 和 ;,打印/删除每一行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-25
        • 2019-11-22
        • 1970-01-01
        • 2011-11-14
        • 2014-05-19
        • 1970-01-01
        相关资源
        最近更新 更多