【问题标题】:from xyz to matrix with awk使用 awk 从 xyz 到矩阵
【发布时间】:2011-10-26 16:55:18
【问题描述】:

我有一个问题,我设法通过变通解决了,所以我在这里希望向你学习更优雅的解决方案;-)

我必须解析一个程序的输出:它会像这样写一个包含三列 x y z 的文件

1 1 11  
1 2 12  
1 3 13  
1 4 14  
2 1 21  
2 2 22  
2 3 23  
2 4 24  
3 1 31  
3 2 32  
3 3 33  
3 4 34  
4 1 41  
4 2 42  
4 3 43  
4 4 44  

在这样的矩阵中

11 12 13 14  
21 22 23 24  
31 32 33 34  
41 42 43 44  

我用这样的两行 bash 脚本解决了

dim_matrix=$(awk 'END{print sqrt(NR)}' file_xyz) #since I know that the matrix has to be squared and there are no blank lines in the file_xyz  
awk '{printf("%s%s",$3, !(NR%'${dim_matrix}'==0) ? OFS :ORS ) }' file_xyz  

您能否建议我一种仅使用 awk 执行相同操作的方法?

【问题讨论】:

    标签: matrix awk


    【解决方案1】:

    awk 不做真正的多维数组,但你可以用正确构造的字符串来伪造它:

    awk '
      {mx[$1 "," $2] = $3}
      END {
        size=sqrt(NR)
        for (x=1; x<=size; x++) {
          for (y=1; y<=size; y++)
              printf("%s ",mx[x "," y])
          print ""
        }
      }
    ' filename
    

    您可以通过一次 awk 调用和对 wc 的调用来完成您的示例

    awk -v "nlines=$(wc -l < filename)" '
      BEGIN {size = sqrt(nlines)}
      {printf("%s%s", $3, (NR % size == 0 ? ORS : OFS))
    }' filename
    

    【讨论】:

    • 也许我找到了一个更短的脚本... awk ' {arr[c++]=$3} END{ size=sqrt(NR) for (c=0;c
    • 对我来说,关于 awk 的关键是脚本的布局:condition {body} condition {body} ... -- 只有在给定条件为真时,主体才会执行。空白条件意味着将为每一行执行正文。空白正文隐含为{print $0}
    【解决方案2】:

    一个“不那么”可读的版本:

    awk '($0=$NF x)&&ORS=NR%4?FS:RS' infile
    

    根据 OP 的要求添加的参数:

    awk '
      ($0 = $NF x) && ORS = NR % n ? FS : RS
      ' n="$1" infile
    

    在上面的脚本中,我使用 $1,但您可以使用任何 shell 变量。

    解释如下:

    $0 = $NF - 设置 $0(整个当前输入记录) 到最后一个字段的当前值 ($NF)。

    ORS = NR % n ? FS : RS - 使用三元运算符:

    expression ? return_this_if_true : return_this_otherwise,

    将 OutputRecordSeparator 设置为:

    • 当 NR % n 评估为真时(即返回不同于 0 的值) 将 ORS 设置为 FS 的当前值(FieldSeparator - 运行空白 默认字符)

    • 否则将其设置为 RS(默认为换行符)

    x(一个未初始化的变量,因此在连接中使用时为 NULL 字符串) 需要为了正确处理输出 当最后一个字段为 0(或空字符串)时。 这是因为 awk 中的赋值语句 实际上在这种情况下返回分配的值, 如果 $NF 为 0,则 && 布尔语句的其余部分 将被忽略。

    【讨论】:

    • 太棒了!您还可以让脚本完成所有工作,这样我就不必明确写 NR%4 吗?如果你能解释一下这行 awk 是如何工作的,我也会非常感激。非常感谢!
    • @Mariano,添加了参数和 cmets。
    • 非常感谢 Dimitre,非常感谢您的回答
    【解决方案3】:

    我不完全确定你尝试做什么,试试这个:

    awk 'NR%4==0{print s " " $NF;s="";next}{s=s?s " " $NF:$NF}' file1
    

    【讨论】:

    • 命令 dint 在 Solaris 的 awk 中工作......它与 nawk 思想完美地工作......
    • @Chris 我不想明确写 file_xyz 的行数我希望 awk 会这样做,将这个数字存储在内存中并用它来格式化矩阵文件......对不起糟糕的解释;-) 谢谢
    猜你喜欢
    • 2013-08-20
    • 2014-05-10
    • 2013-02-18
    • 2012-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    相关资源
    最近更新 更多