如何将逐行的重复元素的值转换为列?

huangapple go评论57阅读模式
英文:

How to convert values of recurring elements row by row to columns?

问题

I receive an output of some script that gives rows containing element and its value.
And there are only 3 elements that repeated with different values.
Want to convert them to columns with element name as column name and then values per column.

我收到一个脚本的输出,其中包含包含元素及其值的行。
只有3个元素,但值不同。
希望将它们转换为以元素名称为列名,然后是每列的值。

I have an output that gathers some server info and put it in file output.txt that looks like following:

我有一个输出,汇总了一些服务器信息,并将其放入名为output.txt的文件中,如下所示:

real	0m0.537s
user	0m0.077s
sys	0m0.082s

real	0m0.512s
user	0m0.076s
sys	0m0.083s

real	0m0.498s
user	0m0.072s
sys	0m0.087s

So using google I handled it and with the following commands put all values into columns named real user and sys as following:

所以,我使用谷歌处理了它,并使用以下命令将所有值放入名为real user和sys的列中,如下所示:

$ sed -i '/^$/d' output.txt
$ awk -F " " '{ print $2 }' output.txt > output2.txt
$ paste -d'\t' - - - < output2.txt | awk 'BEGIN { print "real\tuser\tsys"} {print $0}'

so the output looks like this one:

所以输出如下所示:

real	user	sys
0m0.537s	0m0.077s	0m0.082s
0m0.512s	0m0.076s	0m0.083s
0m0.498s	0m0.072s	0m0.087s

So I have 2 questions.

  1. How to make column name to fit the column?
  2. There should be a way to perform all this ugly stuff using one-liner. Does anyone have this one-liner?

所以我有两个问题。

  1. 如何使列名适应列的宽度?
  2. 有没有一种方法可以使用单行命令执行所有这些繁琐的操作?有人有这个单行命令吗?
英文:

I receive an output of some script that gives rows containing element and it's value.
And there are only 3 elements that repeated with different values.
Want to convert them to columns with element name as column name and then values per column.

I have an output that gathers some server info and put it in file output.txt that looks like following:

real	0m0.537s
user	0m0.077s
sys	0m0.082s

real	0m0.512s
user	0m0.076s
sys	0m0.083s

real	0m0.498s
user	0m0.072s
sys	0m0.087s

So using google I handled it and with the following commands put all values into columns named real user and sys as following:

$ sed -i &#39;/^$/d&#39; output.txt
$ awk -F &quot; &quot; &#39;{ print $2 }&#39; output.txt &gt; output2.txt
$ paste -d&#39;\t&#39; - - - &lt; output2.txt | awk &#39;BEGIN { print &quot;real\tuser\tsys&quot;} {print $0}&#39;

so the output looks like this one:

real	user	sys
0m0.537s	0m0.077s	0m0.082s
0m0.512s	0m0.076s	0m0.083s
0m0.498s	0m0.072s	0m0.087s

So I have 2 questions.

  1. How to make column name to fit the column?
  2. There should be a way to perform all this ugly stuff using one-liner. Does anyone have this one-liner?

答案1

得分: 1

以下是已翻译好的内容:

你可以使用 awk 轻松完成这个任务。

脚本假设示例中始终有完整的3行组,并且sys是最后一行。

或者更短一些的方式:

如果你想要一行命令,去掉换行和空格。

输出结果(以制表符分隔):

如何对齐列标题与数据取决于你的需求。

基于这个假设,修复这个问题的一种方法是在打印标题时使用两个制表符:

或者你可以使用 printf 来控制字段宽度。

打印:

英文:

You can easily do this with awk.

The script assumes there are always complete groups of 3 lines as in the example and that sys is the last.

awk &#39;BEGIN { print &quot;real\tuser\tsys&quot; }
$1==&quot;real&quot; { r=$2 }
$1==&quot;user&quot; { u=$2 }
$1==&quot;sys&quot; { s=$2; print r &quot;\t&quot; u &quot;\t&quot; s }&#39; output.txt

or shorter

awk &#39;BEGIN { print &quot;real\tuser\tsys&quot; }
/^r/ { r=$2 }
/^u/ { u=$2 }
/^s/ { s=$2; print r &quot;\t&quot; u &quot;\t&quot; s }&#39; output.txt

If you want a one-liner, remove line breaks and spaces.

awk &#39;BEGIN{print &quot;real\tuser\tsys&quot;}/^r/{r=$2}/^u/{u=$2}/^s/{s=$2;print r&quot;\t&quot;u&quot;\t&quot;s}&#39; output.txt

Resulting output (tab-separated):

real    user    sys
0m0.537s        0m0.077s        0m0.082s
0m0.512s        0m0.076s        0m0.083s
0m0.498s        0m0.072s        0m0.087s

How to align the column headings with the data depends on what you need.

Since the string length of the data is 8 characters while the headings are 3 or 4 characters long, the TAB positions (with default TAB width 8) characters are different.

Based on this assumption, one way to fix this is to use two tabs when printing the headings:

BEGIN { print &quot;real\t\tuser\t\tsys&quot; }

Or you could use printf with field with.

awk &#39;function myprint(a, b, c) {
    printf(&quot;%-10s %-10s %-10s\n&quot;, a, b, c)
}
BEGIN { myprint(&quot;real&quot;, &quot;user&quot;, &quot;sys&quot;) }
/^r/ { r=$2 }
/^u/ { u=$2 }
/^s/ { s=$2; myprint(r, u, s) }&#39; output.txt

prints

real       user       sys
0m0.537s   0m0.077s   0m0.082s
0m0.512s   0m0.076s   0m0.083s
0m0.498s   0m0.072s   0m0.087s

答案2

得分: 0

You can format any text into columns like this:

$ column -t file.txt
real      user      sys
0m0.537s  0m0.077s  0m0.082s
0m0.512s  0m0.076s  0m0.083s
0m0.498s  0m0.072s  0m0.087s

Depending on the version of "column" you have (most Linux should be fine), you can probably solve the whole problem like this:

$ sed 's/^\S*//' output.txt | xargs -n3 echo | column -t -N real,user,sys
real      user      sys
0m0.537s  0m0.077s  0m0.082s
0m0.512s  0m0.076s  0m0.083s
0m0.498s  0m0.072s  0m0.087s

The "sed" removes the first column, the "xargs" groups the values into threes, and the "column" aligns everything and adds the headers.

英文:

You can format any text into columns like this:

$ column -t file.txt
real      user      sys
0m0.537s  0m0.077s  0m0.082s
0m0.512s  0m0.076s  0m0.083s
0m0.498s  0m0.072s  0m0.087s

Depending what version of "column" you have (most Linux should be fine), you can probably solve the whole problem like this:

$ sed &#39;s/^\S*//&#39; output.txt | xargs -n3 echo | column -t -N real,user,sys
real      user      sys
0m0.537s  0m0.077s  0m0.082s
0m0.512s  0m0.076s  0m0.083s
0m0.498s  0m0.072s  0m0.087s

The "sed" removes the first column, the "xargs" groups the values into threes, and the "column" aligns everything and adds the headers.

huangapple
  • 本文由 发表于 2023年5月10日 23:45:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76220387.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定