输入:
20210602_1234_abc.txt
20210603_1234_def.txt
20210507_5678_abc.txt
20210607_5678_def.txt
输出:
20210603_1234_def.txt
20210607_5678_def.txt
我的脚本应首先根据第二列(此处为 1234 和 5678)进行搜索,然后选择与其关联的最大日期的文件(在本例中)20210603 和 20210607。
如何通过 UNIX shell 脚本获得这个?
答案1
对于zsh
shell,假设这些文件位于当前目录中:
$ ls
20210507_5678_abc.txt 20210602_1234_abc.txt 20210603_1234_def.txt 20210607_5678_def.txt
$ typeset -A h; for f (*_*_*.txt) h[${${(s[_])f}[2]}]=$f; print -rC1 - $h
20210603_1234_def.txt
20210607_5678_def.txt
在哪里
- 的扩展
*_*_*.txt
将按词法排序,因此也按时间顺序排序。 ${(s[_])f}
分裂$f
于_
${...[2]}
获取该分割产生的第二个字段h[that]=$f
h
A
:在该循环中,为 key 关联数组的元素that
分配了完整的文件名。由于排序,最终您将获得给定日期的最新日期that
print -rC1 -- $h
: s 列上的print
哈希值aw 。r
1
C
如果编写脚本,您可能需要对其进行一些分解以提高易读性:
typeset -A max
for file in *_*_*.txt(N); do
parts=( ${(s[_]file} )
max[$parts[2]]=$file
done
print -rC1 -- $max
(这里还添加N
(nullglob) glob 限定符以避免该 glob 与任何文件不匹配时出现错误)。
答案2
使用awk
并假设输入来自文本文件(问题从未以任何方式指定):
$ awk -F '_' 'max[$2] < $1 { max[$2] = $1; maxline[$2] = $0 } END { for (i in maxline) print maxline[i] }' file
20210607_5678_def.txt
20210603_1234_def.txt
这将每个输入行视为一组_
- 分隔的字段。该max
数组跟踪给定第二个字段的键的第一个字段的最大值,并且maxline[i]
是与 中的最大值相对应的整行max[i]
。
当找到某个键的新最大值时,该键的max
和maxline
值都会更新。最后,maxline
打印所有字符串。
使用sort
:
$ sort -t _ -k 1,1nr file | sort -s -u -t _ -k 2,2
20210603_1234_def.txt
20210607_5678_def.txt
第一个按第一个分隔字段以相反的数字顺序对sort
整个文件进行排序。_
第二个sort
对第二个字段进行排序,并且仅保留该字段的任何值的第一行。该-u
选项sort
使实用程序丢弃带有已经看到的排序键的行,并-s
确保稳定的正在使用排序算法(即保证具有相同键的行不会重新排序)。