gawk:为 1 个或多个多字段文件模拟 uniq -cd,合并重复项详细信息并使用计数和路径格式化输出
gawk: simulate uniq -cd for 1 or more multifield files, merging duplicates details and formatting output with counts and paths
输入是 1 个或多个包含文件名列表及其路径的文件,以“/”分隔
(来自重新排列的 ls/dir 输出)
file1 / path1
file2 / path2
file3 / path3
file4 / path4
file3 / path5
...
期望的输出是相似的,除了我想要它们各自的计数和相关路径的重复项
(在同一行上,用“/”分隔或在每个重复的文件名后缩进):
1 / file1 / path1
1 / file2 / path2
2 / file3 / path3-1 / path3-2
1 / file4 / path4
...
或
1 / file1 / path1
1 / file2 / path2
2 / file3 / path3-1
path3-2
1 / file4 / path4
...
现在我有一些大的 awk 混乱,至少它做了一些事情,但我希望他们的方法更简洁、轻便,也许更快!因为我没有找到如何避免将所有行存储在 tmp var...
gawk -F/ -v "tot=c" "{a[]++;l[]=;m[]=;if (a[]>1) m[]=m[]FS;} END {for (i in a) {print a[i],FS,l[i],FS,m[i]; c+=a[i]};print c}" file1 file2 > out
^ ^ here, it doesn't keep ^
^ prev path and add new ^
^ ^[*]
所以,问题是要保留以前的重复路径,并且只在最后一次出现时输出它。
:[*]: 另外:
添加的 var c 应该计算重复项的总数,如果我在星号'位置添加' if (a[i]>1) '(它(然后输出为最后一行),它就会这样做,但是然后只打印副本...
所以,比 运行 这个命令两次更好,也许有人会一次性提出解决方案 :)
注:
它们在路径中没有 /,它们是 windows 路径(也不在文件名中!)
但路径和文件名可以包含任何允许的花式字符(尤其是网页快捷方式)
在 MSdos 批处理中使用 Gnuwin 二进制文件,因此如果需要,请将 " 替换为 ' &v/v
谢谢
$ awk -F/ -v OFS=' / ' '{c[]++; v[]=( in v?v[] OFS:"")}
END {for(k in c) print c[k],k,v[k]}' file
1 / file1 / path1
1 / file2 / path2
2 / file3 / path3 / path5
1 / file4 / path4
但是,如果您的路径值中有 /
,这将不起作用...
鉴于 input.txt 包含:
file1 / path1
file2 / path2
file3 / path3
file4 / path4
file3 / path5
和pgm.awk包含:
BEGIN{
FS="/"
}
{
a[] = a[] "/"
}
END{
for(i in a){
n=split(a[i], b)
if(n == 2){
print n-1 "/" i a[i]
} else {
p=n-1 "/" i
for(j=2; j<=n; j++){
p=p "/" b[j] "-" j-1
}
print p
}
}
}
运行:
gawk -f pgm.awk input.txt
输出:
1/ file1 / path1
1/ file2 / path2
2/ file3 / path3-1/ path5-2
1/ file4 / path4
输入是 1 个或多个包含文件名列表及其路径的文件,以“/”分隔 (来自重新排列的 ls/dir 输出)
file1 / path1
file2 / path2
file3 / path3
file4 / path4
file3 / path5
...
期望的输出是相似的,除了我想要它们各自的计数和相关路径的重复项 (在同一行上,用“/”分隔或在每个重复的文件名后缩进):
1 / file1 / path1
1 / file2 / path2
2 / file3 / path3-1 / path3-2
1 / file4 / path4
...
或
1 / file1 / path1
1 / file2 / path2
2 / file3 / path3-1
path3-2
1 / file4 / path4
...
现在我有一些大的 awk 混乱,至少它做了一些事情,但我希望他们的方法更简洁、轻便,也许更快!因为我没有找到如何避免将所有行存储在 tmp var...
gawk -F/ -v "tot=c" "{a[]++;l[]=;m[]=;if (a[]>1) m[]=m[]FS;} END {for (i in a) {print a[i],FS,l[i],FS,m[i]; c+=a[i]};print c}" file1 file2 > out
^ ^ here, it doesn't keep ^
^ prev path and add new ^
^ ^[*]
所以,问题是要保留以前的重复路径,并且只在最后一次出现时输出它。
:[*]: 另外: 添加的 var c 应该计算重复项的总数,如果我在星号'位置添加' if (a[i]>1) '(它(然后输出为最后一行),它就会这样做,但是然后只打印副本... 所以,比 运行 这个命令两次更好,也许有人会一次性提出解决方案 :)
注:
它们在路径中没有 /,它们是 windows 路径(也不在文件名中!)
但路径和文件名可以包含任何允许的花式字符(尤其是网页快捷方式)
在 MSdos 批处理中使用 Gnuwin 二进制文件,因此如果需要,请将 " 替换为 ' &v/v
谢谢
$ awk -F/ -v OFS=' / ' '{c[]++; v[]=( in v?v[] OFS:"")}
END {for(k in c) print c[k],k,v[k]}' file
1 / file1 / path1
1 / file2 / path2
2 / file3 / path3 / path5
1 / file4 / path4
但是,如果您的路径值中有 /
,这将不起作用...
鉴于 input.txt 包含:
file1 / path1
file2 / path2
file3 / path3
file4 / path4
file3 / path5
和pgm.awk包含:
BEGIN{
FS="/"
}
{
a[] = a[] "/"
}
END{
for(i in a){
n=split(a[i], b)
if(n == 2){
print n-1 "/" i a[i]
} else {
p=n-1 "/" i
for(j=2; j<=n; j++){
p=p "/" b[j] "-" j-1
}
print p
}
}
}
运行:
gawk -f pgm.awk input.txt
输出:
1/ file1 / path1
1/ file2 / path2
2/ file3 / path3-1/ path5-2
1/ file4 / path4