我想按特定顺序对以下文本行进行排序。我使用的命令sort
是删除空格并将所有行捆绑在一起而不使用空格分隔并将它们按字母顺序排列。每个块有 8 行行数据。
会话:cabSessionID:052FPBP6Q6X2XGERWHBT
cabLoginID:053XCDTF8D4J6PD3BG8P
登录名:jack
userAgent:Mozilla/5.0
sessionStartTime:2018-10-01T01:04:10.899Z
内存信息:jsHeapSizeLimit:2217857988使用
的totalJSHeapSize:42358792
JHeapSize:36482584会话:cabSessionID:052FPBP6Q6X2XGERWHJE
cabLoginID:053XCDTF8D4J6PD3BG8P
登录名:jack
userAgent:Mozilla/5.0
sessionStartTime:2018-10-01T01:16:41.558Z
内存信息:jsHeapSizeLimit:2217857988
总JSHeapSize:17775404 0
使用JSHeapSize:44842320内存信息:jsHeapSizeLimit:2217857988
总JSHeapSize:45252608
使用JSHeapSize:24555080
会话:cabSessionID:055S75T4QC8JYC4Q0456
cabLoginID:053XCDTF8D4J6PD3BG8P
登录名:frank
userAgent:Mozilla/5.0
sessionStartTime:2018- 10-23T19:11:11.871Z
我希望最终结果是这样的:
登录名:jack
cabLoginID:053XCDTF8D4J6PD3BG8P
会话:cabSessionID:052FPBP6Q6X2XGERWHBT
userAgent:Mozilla/5.0
sessionStartTime:2018-10-01T01:04:10.899Z
内存信息:jsHeapSizeLimit:2217857988使用的
总JSHeapSize:42358792
JHeapSize:36482584登录名:jack
cabLoginID:053XCDTF8D4J6PD3BG8P
会话:cabSessionID:052FPBP6Q6X2XGERWHJE
userAgent:Mozilla/5.0
sessionStartTime:2018-10-01T01:16:41.558Z
内存信息:jsHeapSizeLimit:2217857988
总JSHeapSize:17775404 0
使用JSHeapSize:44842320登录名:fred
cabLoginID:053XCDTF8D4J6PD3BG8P
会话:cabSessionID:055S75T4QC8JYC4Q0456
userAgent:Mozilla/5.0
sessionStartTime:2018-10-23T19:11:11.871Z
内存信息:jsHeapSizeLimit:2217857988
总计JSHeapSize:4525第2608章
使用JSHeapSize:24555080
答案1
由于您想要硬编码“排序”,请让 awk 编译关联数组中每个块的数据,然后按您想要的顺序打印该数组:
脚本文件.awk
BEGIN {
FS=":"
}
/./ {
values[$1]=$0
}
/^$/ {
print values["loginName"]
print values["cabLoginID"]
print values["session"]
print values["userAgent"]
print values["sessionStartTime"]
print values["memoryInfo"]
print values["totalJSHeapSize"]
print values["usedJSHeapSize"]
print ""
delete values
}
END {
print values["loginName"]
print values["cabLoginID"]
print values["session"]
print values["userAgent"]
print values["sessionStartTime"]
print values["memoryInfo"]
print values["totalJSHeapSize"]
print values["usedJSHeapSize"]
}
然后运行:
awk -f scriptfile.awk < input
作为替代方案,如果您不关心块行的顺序,但确实希望它们仍然保持一致的顺序,并且您有 GNU awk,
gnuscript.awk
BEGIN {
FS=":"
PROCINFO["sorted_in"]="@val_str_asc";
}
/./ {
values[$1]=$0
}
/^$/ {
asort(values)
for (element in values)
print values[element]
print ""
delete values
}
END {
asort(values)
for (element in values)
print values[element]
}
上面的脚本按字母顺序打印每个块的行:
cabLoginID:053XCDTF8D4J6PD3BG8P
loginName:jack
memoryInfo:jsHeapSizeLimit:2217857988
session:cabSessionID:052FPBP6Q6X2XGERWHBT
sessionStartTime:2018-10-01T01:04:10.899Z
totalJSHeapSize:42358792
usedJSHeapSize:36482584
userAgent:Mozilla/5.0
...
答案2
您可以在段落模式下使用 Perl,并使用散列定义自定义排序顺序,例如
perl -00 -F'\n' -ne '
our %rank;
BEGIN {
%rank = (
loginName => 1,
cabLoginID => 2,
session => 3,
userAgent => 4,
sessionStartTime => 5,
memoryInfo => 6,
totalJSHeapSize => 7,
usedJSHeapSize => 8
);
}
%h = ();
map { ($k,$v) = split(/:/, $_, 2); $h{$k} = $v } @F;
for $k (sort { $rank{$a} <=> $rank{$b} } keys %h) { print "$k:$h{$k}\n" };
print "\n";
' file
答案3
如果您想一遍又一遍地以相同的方式对一组行进行排序,我认为没有一个简单的单行代码可以做到这一点。
由于我担心 awk 由于时间中的冒号而无法捕获所有字符串,因此我编写了这个快速的小 shell 脚本。这实际上是按块对它们进行排序。它在块中的顺序由 printf 决定。更新它以满足您的需求。
#!/bin/bash
declare -A arr
(
while read l; do
if [[ "" == "${l}" ]]; then
printf "loginName:%s~cabLoginID:%s~session:%s~userAgent:%s~sessionStartTime:%s~memoryInfo:%s~totalJSHeapSize:%s~usedJSHeapSize:%s~\n" ${arr[loginName]} ${arr[cabLoginID]} ${arr[session]} ${arr[userAgent]} ${arr[sessionStartTime]} ${arr[memoryInfo]} ${arr[totalJSHeapSize]} ${arr[usedJSHeapSize]}
unset arr
declare -A arr
continue
fi
k=${l%%:*}
v=${l#*:}
arr[${k}]=${v}
done
printf "loginName:%s~cabLoginID:%s~session:%s~userAgent:%s~sessionStartTime:%s~memoryInfo:%s~totalJSHeapSize:%s~usedJSHeapSize:%s~\n" ${arr[loginName]} ${arr[cabLoginID]} ${arr[session]} ${arr[userAgent]} ${arr[sessionStartTime]} ${arr[memoryInfo]} ${arr[totalJSHeapSize]} ${arr[usedJSHeapSize]}
) | sort | tr '~' '\n'
exit 0
答案4
也试试
awk '
BEGIN {for (n=split("loginName cabLoginID session userAgent sessionStartTime memoryInfo totalJSHeapSize usedJSHeapSize", T); n; n--) FLSQ[T[n]] = n
}
{for (i=1; i<=NF; i++) {n = split ($i, T, ":")
OUT[FLSQ[T[1]]] = $i
}
for (i=1; i<=NF; i++) $i = OUT[i]
split ("", OUT)
}
1
' RS="" ORS="\n\n" FS="\n" OFS="\n" file
loginName:jack
cabLoginID:053XCDTF8D4J6PD3BG8P
session:cabSessionID:052FPBP6Q6X2XGERWHBT
userAgent:Mozilla/5.0
sessionStartTime:2018-10-01T01:04:10.899Z
memoryInfo:jsHeapSizeLimit:2217857988
totalJSHeapSize:42358792
usedJSHeapSize:36482584
.
.
.
在该BEGIN
部分中,它通过为每个字段标签分配一个升序数字来定义每个记录输出中的字段序列。当对多行记录进行操作时,将标签拆分到数组中T
,它OUT
用整个字段填充数组,并按标签的编号进行索引。打印记录之前的最后一个操作是重建整个 $0(= 记录)。所有字段和记录分隔符都必须适应多行记录布局。