我写了一个脚本来修饰我的.bash_history文件,过滤"无趣的"来自持久历史记录的ls
命令。
(我知道那里有HISTIGNORE
变量,但是这也会从当前会话的内存历史记录中排除这些命令。我觉得在范围内包含它们很有用一个会话,但不会在会话中持续存在。)
历史记录文件可以包含带有嵌入换行符的多行历史记录条目,因此条目以时间戳分隔。该脚本采用如下输入文件:
#1501304269
git stash
#1501304270
ls
#1501304318
ls | while IFS= read line; do
echo 'line is: ' $line
done
并过滤掉单行ls
,man
和cat
命令,生成:
#1501304269
git stash
#1501304318
ls | while IFS= read line; do
echo 'line is: ' $line
done
请注意,多行条目是未过滤的 - 我认为如果它们足够有趣以保证多行,那么它们值得记住。
我在Awk中实现了它,但我一直在阅读Sed的多线功能(N
,h
,H
,x
,等等)我想为此目的而尝试。如果不出意外,我很想将两者比作速度。
这是Awk脚本:
/^#[[:digit:]]{10}$/ {
timestamp = $0
histentry = ""
next
}
$1 ~ /^(ls?|man|cat)$/ {
if (! timestamp) {
print
} else {
histentry = $0
}
next
}
timestamp {
print timestamp
timestamp = ""
}
histentry {
print histentry
histentry = ""
}
{ print }
可以使用Sed完成吗?
答案 0 :(得分:1)
当然可以用sed完成。下面是一个使用GNU seds -z
选项的示例,它允许我们一次处理整个文件而不是行的工作行:
sed -rz "s/(#[0-9]{10}\n(cat|ls|man)\n)+(#[0-9]{10}\n|$)/\3/g;" yourfile
如果一切正常并且您有历史文件的备份,您甚至可以使用GNU sed -i
选项进行就地修改。
-r
选项启用扩展的正则表达式,-z
选项在手册中解释如下:
将输入视为一组行,每行以零字节结束 (ASCII'NUL'字符)而不是换行符。这个选项可以 与'sort -z'和'find -print0'之类的命令一起使用来处理 任意文件名。
基本思路是这样的:一个无趣的命令前面跟着一个时间戳(或者它是文件中的最后一行)。
#[0-9]{10}
取自您的awk脚本(#[0-9]{10}\n(cat|ls|man)\n)+
匹配一个或多个无趣的命令(#[0-9]{10}|$)
第二个时间戳被捕获到\3
(由于位于第三对parens中),以便在替换部分中重复使用,并且替换|$
符合文件末尾的情况