我正在使用以下信息填写信息的文件示例:
name : server1
description : webserver
memory : 32gb
name : server2
memory : 128gb
name : server3
description : appserver
我正在做这样的事情:
cat myfile | egrep -w "name|description|memory" | awk -F" " '{print $3}' >> myfile2
为了从myfile中的第二列获取信息。
然后,我将myfile2格式化为从一个行上的每个服务器获取信息(使用tr替换CRLF),用semicolonn分隔以在Excel上导入它们。
myfile2:
server1;webserver;32gb
server2;128gb
server3;appserver
问题是:当egrep与任何东西都不匹配时(比如server2的描述或server3的内存),myfile2中有一行的间隙......如何用空格替换它?
我想要的文件输出2:
server1的; Web服务器; 32GB
服务器2 ;; 128GB
服务器3;应用程序服务器;;
答案 0 :(得分:2)
声音就像你需要的一样:
$ awk -v RS= -F' *: *|\n' -v OFS=';' '{print $2,$4,$6}' myfile
server1;webserver;32gb
server2;;128gb
如果你想要CRLF行结尾,那么只需在前面添加-v ORS='\r\n'
告诉awk。
不确定为什么你还没有更新你的问题,但听起来这就是你真正需要的:
$ cat file
name : server1
description : webserver
memory : 32gb
name : server2
memory : 128gb
name : server3
description : appserver
$ cat tst.awk
BEGIN{
RS=""
FS=" *: *|\n"
OFS=";"
numNames = split("name description memory",names,/ /)
for (i=1; i<=numNames; i++) {
name2nr[names[i]] = i
}
}
{
delete vals
for (i=1;i<=NF;i+=2) {
vals[name2nr[$i]] = $(i+1)
}
for (i=1; i<=numNames; i++) {
printf "%s%s", vals[i], (i<numNames?OFS:ORS)
}
}
$ awk -f tst.awk file
server1;webserver;32gb
server2;;128gb
server3;appserver;
可以编写添加第一个传递,它只是计算字段名称,而不是在BEGIN部分硬编码,但是字段的输出顺序依赖于它们在输入中出现的顺序,所以不是在这种情况下确定它是值得的。
答案 1 :(得分:1)
我认为不需要在输入数据上使用grep
。 awk
命令几乎可以执行grep
所能完成的所有操作。请考虑以下事项:
awk -F' *: *' '
{
a[$1]=$2;
}
/^memory/ {
printf("%s;%s;%s\n", a["name"], a["description"], a["memory"]);
delete a;
}' myfile
这里的组件如下:
-F...
设置字段分隔符,包括空格。a[$1]=$2
使用每条记录中的数据填充一个短期数组。/^memory/
仅在每个组的最后一行执行此配方... printf(...)
显示您的输出,delete a
可让您重新开始下一个多行记录。你当然可以将这一切压缩到一行:
awk -F' *: *' '{ a[$1]=$2 } /^memory/ { printf("%s;%s;%s\n", a["name"], a["description"], a["memory"]); delete a }' myfile
这是你需要的吗?
<强>更新强>
我看到您修改了问题以包含与上述解决方案不同的示例数据。这是一个应该与当前示例一起使用的更新:
function outp() {
printf("%s;%s;%s\n", a["name"], a["description"], a["memory"]);
}
BEGIN {
seen=0;
FS=" *: *";
}
/^name/ && seen {
outp();
delete a;
}
/^name/ {
seen=1;
}
{
a[$1]=$2;
}
END {
outp();
}
这使用函数(outp()
)来简化事情。它使用seen
变量来确定脚本是否已经看到任何实际数据(否则,/^name/
的第一个匹配将生成空输出)。并继续使用a
数组来收集重要字段。
重要的是要注意,现在,我们假设您在的结尾,而不是假设您将拥有“记忆”。 >开始每条记录。如果这个假设不正确,请说明您认为应该如何相互记录记录(即一个停止和下一个停止的位置)。例如,空行是一个选项。