我正在使用包含以下格式的块的 bash_history 文件:#unixtimestamp\ncommand\n
这是 bash_history 文件的示例:
#1713308636
cat > ./initramfs/init << "EOF"
#!/bin/sh
/bin/sh
EOF
#1713308642
file initramfs/init
#1713308686
cpio -v -t -F init.cpio
#1713308689
cpio -v -t -F init.cpio
#1713308690
ls
#1713308691
ls
我的目标是完全消除重复的块,这意味着时间戳和相关命令。我尝试过使用awk
,但这种方法单独处理行,而不将它们视为块的一部分。
我听说 usingignoredups
可以防止重复数据删除,但在这种情况下它不起作用(除非您重新键入确切的命令),因为重复的命令已经存在。
我很感激有关更有效的方法来实现重复数据删除的建议。
编辑:正如埃德·莫顿在评论中所建议的,这是预期的输出:
#1713308636
cat > ./initramfs/init << "EOF"
#!/bin/sh
/bin/sh
EOF
#1713308642
file initramfs/init
#1713308686
cpio -v -t -F init.cpio
#1713308690
ls
作为解决方法,我向该程序添加了删除功能。但我仍然对使用现有命令的其他方法持开放态度。
您没有在 awk 中显示您的尝试,但以下 awk 程序会打印以下含义的条目
其中命令是唯一的。该计划是:
输出:
请注意,如果“命令”例如
保存在文件中,上面的 awk 程序将跳过它们,例如:
可以调整程序以适应这种情况,但需要更精确地说明问题。例如,如何处理:
使用 Perl,你可以这样做:
最大的假设是,这
^#[0-9]{10}\n
将始终肯定地识别文件中条目的开始。该命令有点密集,但其背后的逻辑是:
^#[0-9]{10}\n
记录分隔符,不消耗分隔符 (<> =~ /^#[0-9]{10}\n.*?(?=^#[0-9]{10}\n|\z)/smg
);正则表达式的细分:
^#[0-9]{10}\n.*?(?=^#[0-9]{10}\n|\z)
#
: 将匹配以字符开头、后跟 10 位数字和换行符的行;然后,它将延迟匹配任何内容(包括换行符),直到找到新出现的^#[0-9]{10}\n
字符串 ( ) 或字符串末尾(避免使用零长度先行断言 ( ) 捕获当前匹配中新发现的出现的) 和允许下一场比赛捕获它);将允许匹配换行符,将允许和在换行符之后和之前进行匹配,并且将允许捕获字符串中模式的多次出现。\z
^#[0-9]{10}\n
?=
s
.
m
^
$
g
它适用于您的样本输入;我还使用空命令(另一个时间戳后面的时间戳)对其进行了测试。
如果发现重复的条目,则第一个条目将被保留,后面的条目将被丢弃。