Ign*_*eLX 12 sed awk text-processing
我有一个文件,其中包含有关在管理程序中运行的 VM 的详细信息。我们运行一些命令并将输出重定向到一个文件。并且是以下格式的可用数据。
Virtual Machine : OL6U5
ID : 0004fb00000600003da8ce6948c441bb
Status : Running
Memory : 65536
Uptime : 17835 Minutes
Server : MyOVS1.vmorld.com
Pool : HA-POOL
HA Mode: false
VCPU : 16
Type : Xen PVM
OS : Oracle Linux 6
Virtual Machine : OL6U6
ID : 0004fb00000600003da8ce6948c441bc
Status : Running
Memory : 65536
Uptime : 17565 Minutes
Server : MyOVS2.vmorld.com
Pool : NON-HA-POOL
HA Mode: false
VCPU : 16
Type : Xen PVM
OS : Oracle Linux 6
Virtual Machine : OL6U7
ID : 0004fb00000600003da8ce6948c441bd
Status : Running
Memory : 65536
Uptime : 17835 Minutes
Server : MyOVS1.vmorld.com
Pool : HA-POOL
HA Mode: false
VCPU : 16
Type : Xen PVM
OS : Oracle Linux 6
Run Code Online (Sandbox Code Playgroud)
此输出因管理程序而异,因为在某些管理程序上,我们有 50 多个虚拟机在运行。上面的文件只是来自管理程序的一个例子,我们只有 3 个虚拟机在运行,因此重定向的文件应该包含几个(N 个虚拟机)的信息
我们需要使用 awk/sed 或 shell 脚本以以下格式获取此详细信息
Virtual_Machine ID Status Memory Uptime Server Pool HA VCPU Type OS
OL6U5 0004fb00000600003da8ce6948c441bb Running 65536 17835 MyOVS1.vmworld.com HA-POOL false 16 Xen PVM Oracle Linux 6
OL6U6 0004fb00000600003da8ce6948c441bc Running 65536 17565 MyOVS2.vmworld.com NON-HA-POOL false 16 Xen PVM Oracle Linux 6
OL6U5 0004fb00000600003da8ce6948c441bd Running 65536 17835 MyOVS1.vmworld.com HA-POOL false 16 Xen PVM Oracle Linux 6
Run Code Online (Sandbox Code Playgroud)
Dig*_*uma 11
如果您有rs(reshape) 实用程序可用,您可以执行以下操作:
rs -Tzc: < input.txt
Run Code Online (Sandbox Code Playgroud)
这提供了与问题中指定的完全相同的输出格式,甚至可以降低到动态列宽。
-T 转置输入数据-z 从每列中的最大值适当地调整列的大小-c: 使用冒号作为输入字段分隔符这适用于任意大小的表,例如:
$ echo "Name:Alice:Bob:Carol
Age:12:34:56
Eyecolour:Brown:Black:Blue" | rs -Tzc:
Name Age Eyecolour
Alice 12 Brown
Bob 34 Black
Carol 56 Blue
$
Run Code Online (Sandbox Code Playgroud)
rs默认情况下在 OS X 上可用(可能还有其他 BSD 机器)。它可以安装在 Ubuntu(和 debian 系列)上:
sudo apt-get install rs
Run Code Online (Sandbox Code Playgroud)
编辑:可扩展到任意数量的输出行,在一个简单的单行for循环中:
for ((i=1;i<=2;i++)); do cut -d: -f "$i" input | paste -sd: ; done | column -t -s:
Run Code Online (Sandbox Code Playgroud)
原答案:
您可以使用bash流程替换将其作为单线执行:
paste -sd: <(cut -d: -f1 input) <(cut -d: -f2 input) | column -t -s:
Run Code Online (Sandbox Code Playgroud)
使其一次处理一个文件的-s选项paste。:设置的分隔符paste被最后的-s选项“捕获”,column通过使字段对齐来美化格式。
cut两个进程替换中的命令分别拉出第一个字段和第二个字段。
输入中是否有空行无关紧要,column -t -s:无论如何都会清理输出。(问题中指定的原始输入中有空行,但它们已被删除。无论空行如何,上述命令都有效。)
输入 - 上面命令中名为“input”的文件的内容:
Virtual_Machine:OL6U7
ID:0004fb00000600003da8ce6948c441bd
Status:Running
Memory:65536
Uptime:17103
Server:MyOVS1.vmworld.com
Pool:HA-POOL
HA:false
VCPU:16
Type:Xen PVM
OS:Oracle Linux 6
Run Code Online (Sandbox Code Playgroud)
输出:
Virtual_Machine ID Status Memory Uptime Server Pool HA VCPU Type OS
OL6U7 0004fb00000600003da8ce6948c441bd Running 65536 17103 MyOVS1.vmworld.com HA-POOL false 16 Xen PVM Oracle Linux 6
Run Code Online (Sandbox Code Playgroud)
小智 3
如果两次遍历文件不是一个(大)问题(只会在内存中存储一行):
awk -F : '{printf("%s\t ", $1)}' infile
echo
awk -F : '{printf("%s\t ", $2)}' infile
Run Code Online (Sandbox Code Playgroud)
对于字段的一般计数,其中可能有许多文件路径:
#!/bin/bash
rowcount=2
for (( i=1; i<=rowcount; i++ )); do
awk -v i="$i" -F : '{printf("%s\t ", $i)}' infile
echo
done
Run Code Online (Sandbox Code Playgroud)
但对于真正通用的转置,这将起作用:
awk '$0!~/^$/{ i++;
split($0,arr,":");
for (j in arr) {
out[i,j]=arr[j];
if (maxr<j){ maxr=j} # max number of output rows.
}
}
END {
maxc=i # max number of output columns.
for (j=1; j<=maxr; j++) {
for (i=1; i<=maxc; i++) {
printf( "%s\t", out[i,j]) # out field separator.
}
printf( "%s\n","" )
}
}' infile
Run Code Online (Sandbox Code Playgroud)
并使其美观(使用制表符\t作为字段分隔符):
./script | |column -t -s $'\t'
Virtual_Machine ID Status Memory Uptime Server Pool HA VCPU Type OS
OL6U7 0004fb00000600003da8ce6948c441bd Running 65536 17103 MyOVS1.vmworld.com HA-POOL false 16 Xen PVM Oracle Linux 6
Run Code Online (Sandbox Code Playgroud)
上面的通用转置代码会将整个矩阵存储在内存中。
对于非常大的文件来说这可能是一个问题。
为了处理问题中发布的新文本,在我看来,两遍 awk 是最好的答案。只要字段存在,一次传递将打印标题字段标题。下一个 awk 遍将仅打印字段 2。在这两种情况下,我都添加了一种删除前导空格和尾随空格的方法(为了更好的格式)。
#!/bin/bash
{
awk -F: 'BEGIN{ sl="Virtual Machine"}
$1~sl && head == 1 { head=0; exit 0}
$1~sl && head == 0 { head=1; }
head == 1 {
gsub(/^[ \t]+/,"",$1); # remove leading spaces
gsub(/[ \t]+$/,"",$1); # remove trailing spaces
printf( "%s\t", $1)
}
' infile
#echo
awk -F: 'BEGIN { sl="Virtual Machine"}
$1~sl { printf( "%s\n", "") }
{
gsub(/^[ \t]+/,"",$2); # remove leading spaces
gsub(/[ \t]+$/,"",$2); # remove trailing spaces
printf( "%s\t", $2)
}
' infile
echo
} | column -t -s "$(printf '%b' '\t')"
Run Code Online (Sandbox Code Playgroud)
周围的{ ... } | column -t -s "$(printf '%b' '\t')"是以漂亮的方式格式化整个表格。
请注意,可以用 ksh、bash 或 zsh"$(printf '%b' '\t')"替换。$'\t'