使用 awk 从 xyz 到矩阵

发布于 2024-12-11 19:00:15 字数 668 浏览 0 评论 0原文

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

我必须解析程序的输出:它

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  

在一个文件中 写入一个三列 xyz 的文件,如下所示像这样的矩阵

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执行相同操作的方法吗?

I have a problem that I managed to solve with a work around so I am here hoping to learn from you more elegant solutions ;-)

I have to parse the output of a program: it writes a file of three columns x y z like this

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  

in a matrix like this

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

I solved with a two line bash script like this

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  

Can you please suggest me a way to perform the same only with awk?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

倾城花音 2024-12-18 19:00:15

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 does not do real multidimensional arrays, but you can fake it with a properly constructed string:

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

You can accomplish your example with a single awk call and a call to wc

awk -v "nlines=$(wc -l < filename)" '
  BEGIN {size = sqrt(nlines)}
  {printf("%s%s", $3, (NR % size == 0 ? ORS : OFS))
}' filename
極樂鬼 2024-12-18 19:00:15

一个“不太”可读的版本:

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 - 使用三元运算符:

表达式? return_this_if_true : return_this_otherwise,

将 OutputRecordSeparator 设置为:

  • 当 NR % n 计算结果为 true 时(即返回值不同于 0)
    将 ORS 设置为 FS 的当前值(FieldSeparator - 空格运行
    默认字符)

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

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

A "not so" readable version:

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

Parameters added as per OP's request:

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

In the script above I'm using $1, but you can use any shell variable.

The explanation follows:

$0 = $NF - set $0 (the entire current input record)
to the current value of the last field ($NF).

ORS = NR % n ? FS : RS - using the ternary operator:

expression ? return_this_if_true : return_this_otherwise,

set the OutputRecordSeparator to:

  • when NR % n evaluates true (i.e. returns value different than 0)
    set ORS to the current value of FS (FieldSeparator - runs of white space
    characters by default)

  • otherwise set it to RS (which defaults to a newline)

The x (an unitialized variable and thus a NULL string when used in concatenation)
is needed in order to handle correctly the output
when the last field is 0 (or an empty string).
This is because the assignement statement in awk
actually in this case returns the assigned value,
if $NF is 0, the rest of the && boolean statement
will be ignored.

人间不值得 2024-12-18 19:00:15

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

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

I am not totally sure what you try do, try this:

awk 'NR%4==0{print s " " $NF;s="";next}{s=s?s " " $NF:$NF}' file1
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文