3 个版本
0.1.6 | 2020年12月12日 |
---|---|
0.1.5 | 2020年12月12日 |
0.1.0 | 2020年12月12日 |
#7 in #removing
11KB
Semiuniq
一个 [希望很快] 的类似 uniq 工具,用于删除文件中的邻近重复行。
构建
构建 semiuniq
需要 Rust 版本至少为 1.36.0。您可以按以下方式构建程序
git clone [email protected]:kljensen/semiuniq.git
cd semiuniq
cargo build --release
程序将被放置在 ./target/release/semiuniq
。
或者,如果您是 homebrew 用户,您可以通过 kljensen/tap tap 安装 semiuniq
,以下任选其一
brew install kljensen/tap/semiuniq
或者
brew tap kljensen/tap
brew install semiuniq
描述
semiuniq
程序读取输入的行并写入“半唯一”的输出行,通过消除彼此邻近的重复行。它类似于 GNU uniq,但 1) 不需要排序输入,2) 不保证输出行的全局唯一性。
这有什么用?这很有用,因为在许多类型的日志文件中,重复的行很可能彼此靠近。例如,我的 shell 历史看起来像这样
cd foo
pipenv run ansible-playbook -vvvv -i hosts.yaml playbooks/default.yaml -l hydrogen --tags unbound
vim playbooks/default.yaml
pipenv run ansible-playbook -vvvv -i hosts.yaml playbooks/default.yaml -l hydrogen --tags unbound
cd ..
tig
cd foo
pipenv run ansible-playbook -vvvv -i hosts.yaml playbooks/default.yaml -l hydrogen --tags unbound
ssh hydrogen
正如您所看到的,在这个会话中,我多次输入了相同的长 ansible-playbook
命令,但它被一些管理琐事分隔开了。现在想象一下,如果我的 shell 历史长达 58,000 行(正如它那样),我想要通过使用类似 fzf 的东西在历史中搜索该命令,我会看到很多重复的行。我可以使用 sort
和 uniq
来消除这些行,但这将意味着对 58,000 行历史进行排序。使用 semiuniq
,我在不排序的情况下对整个历史进行一次扫描,并使用 最近最少使用缓存 删除历史中“靠近”的重复行
这对我很有用。我希望它对您也很有用。
示例用法
以下一系列 shell 命令展示了在示例文件中使用 semiuniq
的方法。
prompt> cat target/temp.txt
dog
dog
dog
dog
fish
fish
fish
fish
1
2
3
4
fish
dog
1
2
3
4
5
dog
prompt> cat target/temp.txt | semiuniq 0
dog
dog
dog
dog
fish
fish
fish
fish
1
2
3
4
fish
dog
1
2
3
4
5
dog
prompt> cat target/temp.txt | semiuniq 1
dog
fish
1
2
3
4
fish
dog
1
2
3
4
5
dog
prompt> cat target/temp.txt | semiuniq 5
dog
fish
1
2
3
4
dog
1
2
3
4
5
dog
prompt> cat target/temp.txt | semiuniq 10
dog
fish
1
2
3
4
5
正如您所看到的,semiuniq 0
的输出与输入相同。使用semiuniq 1
,其行为类似于GNU uniq
:如果当前行与前一行相同,则不打印该行。使用semiuniq 5
,如果当前行在过去5行中出现过,则不打印该行。依此类推,使用semiuniq 1000
,如果当前行与之前1000行中的任何一行相同,则不打印。 (行的哈希存储在内存中,而不是行本身。我们使用LruCache的默认哈希,它是aHash。)
基准测试
这是一个糟糕的基准测试。我使用了我的shell历史记录,将semiuniq
与sort | uniq
进行比较。显然,不排序可以节省大量时间,duh。
promt> wc -l example-shell-history.txt
54631 example-shell-history.txt
prompt> alias cmd1="cat ./example-shell-history.txt|sort|uniq >/dev/null"
prompt> time cmd1
cat ./example-shell-history.txt 0.00s user 0.01s system 11% cpu 0.060 total
sort 0.16s user 0.01s system 85% cpu 0.197 total
uniq > /dev/null 0.06s user 0.00s system 30% cpu 0.196 total
prompt> alias cmd2="cat ./example-shell-history.txt|semiuniq 1000 >/dev/null"
prompt> time cmd2
cat ./example-shell-history.txt 0.00s user 0.01s system 8% cpu 0.095 total
~/src/github.com/kljensen/semiuniq/target/release/semiuniq 500 > /dev/null 0.07s user 0.02s system 98% cpu 0.096 total
当窗口大小为500时,semiuniq
允许通过更多的重复行。
prompt> cat ./example-shell-history.txt|sort|uniq |wc -l
54112
prompt> cat ./example-shell-history.txt|semiuniq 500 |wc -l
54204
寻求帮助与灵感
如果您能使这段代码变得更好,请向我发送一个pull request!我对Rust一无所知,所以我不得不使用duckduckgo来编写这段代码。这里的大部分内容都是从以下内容复制粘贴的:
许可证(Unlicense)
这是免费且无负担的软件,已发布到公共领域。
任何人都可以免费复制、修改、发布、使用、编译、销售或以任何方式分发此软件,无论是源代码形式还是编译的二进制文件,无论用于商业目的还是非商业目的。
在承认版权法的司法管辖区,本软件的作者或作者将本软件的任何和所有版权利益捐赠给公共领域。我们做出这项捐赠是为了公众利益,损害我们的继承人后继者的利益。我们意图使这项捐赠成为一项永久放弃本软件在版权法下所有现有和未来权利的明确行为。
本软件按“原样”提供,不提供任何形式的保证,无论是明示的还是暗示的,包括但不限于适销性、特定目的适用性和非侵权性保证。在任何情况下,作者均不对任何索赔、损害或其他责任承担责任,无论是基于合同、侵权或其他行为,无论是在软件或其使用或任何其他相关活动中产生的。
有关更多信息,请参阅http://unlicense.org/
依赖项
~2MB
~24K SLoC