shell - 如何在不使用 tac 的情况下从下到上搜索文件中的匹配字符串?
问题描述
我需要遍历一个文件,从文件底部开始,直到我到达出现“2021-04-04”的第一个日期,然后返回该日期。我不想从头开始,一直到第一行,因为每个文件中有数千行。
示例文件内容:
random text on first line
random text on second line
2021-01-01
random text on fourth line
2021-02-03
random text on sixth line
2021-03-03
2021-04-04
Random text on ninth line
tac
在 MacOS 上不可用,所以我无法使用它。
解决方案
“千行”不算什么,一眨眼就处理完了。一旦你进入数以千万计的行,那么如果有必要,你就可以开始考虑提高性能。
所有你需要的是:
awk '/[0-9]{4}(-[0-9]{2}){2}/{line=$0} END{if (line!="") print line}' file
5s
这是第 3 次运行时间比较,用于在由 生成的 100000 行文件中查找包含 2 个或更多连续的最后一行seq 100000 > file100k
,即目标字符串距输入文件末尾仅 45 行,有和没有tac
:
$ time awk '/5{2}/{line=$0} END{if (line!="") print line}' file100k
99955
real 0m0.056s
user 0m0.031s
sys 0m0.000s
$ time tac file100k | awk '/5{2}/{print; exit}'
99955
real 0m0.056s
user 0m0.015s
sys 0m0.030s
如您所见,两者都在几分之一秒内运行,并且 usingtac
并没有提高执行速度。切换到 tac+grep 也不会让它更快,它仍然只需要 1/20 秒:
$ time tac file100k | grep -m1 '5\{2\}'
99955
real 0m0.057s
user 0m0.015s
sys 0m0.015s
但是,如果您将来确实需要它,tac
如果您没有它,这里是如何实现高效的:
$ mytac() { cat -n "${@:--}" | sort -k1,1rn | cut -d$'\t' -f2-; }
$ seq 5 | mytac
5
4
3
2
1
上面的mytac()
函数只是将行号添加到输入中,对它们进行反向排序,然后再次删除它们。如果您cat
不必-n
添加行号,那么您可以使用nl
它(如果有的话)或awk -v OFS='\t' '{print NR, $0}'
将始终工作。
推荐阅读
- go - 不允许通过经销商 API 将第一个用户添加到新配置的客户
- python - 使用“Bf”格式化程序解包结构
- bash - 在shell脚本中为文本文件分配名称
- json - 在读取/加载时保留原始 JSON 作为 Spark DataFrame 中的列?
- python - 运行烧瓶应用程序时Nginx 502 Bad Gateway错误,但可以手动运行
- javascript - 简单的 javascritp 幻灯片 - 添加控件
- java - java Mail API 用于从 java 程序发送电子邮件,但显示 SMTP 协议错误
- angularjs - 控制器值未绑定到角度 js 中的 HTML
- memory-management - 链接器错误:“地址错误
对于零页符号 “! - grafana - Prometheus / Grafana 最高价值和时间