解释
我想从Linux历史记录命令中获取所有行apt-get install
,但是我想要列出已安装的内容我还希望将这些行加入其中并删除apt-get install
从中。稍后将使用它来创建在另一台计算机上安装相同软件包的命令。
只能使用我必须与awk, sed etc
结合的一个greps吗?
答案 0 :(得分:4)
只有grep
(因为你问过):
grep -Pow '^\s*(?:sudo\s+)?apt-get\s+install\s+\K.*' ~/.bash_history \
|grep -Eow '\S+' |sort -u
这会过滤apt-get install命令的历史记录文件,并在安装后显示这些命令的一部分(\K
是grep -Po
的绝佳工具)。第二个grep
调用将每个包放在其自己的行上,以便sort
命令可以删除重复项(sort -u
仅显示唯一条目)。如果您需要按时间顺序排序,则无法在没有更强大工具的情况下删除重复的条目。
这需要grep中的libprce支持(这些天大多数部署都很常见),并不像其他解决方案那样优雅,但它确实满足您的基本要求。
仅使用awk
:
awk '
/^sudo/ { sub(/^sudo/,"") }
/^ *apt-get install/ {
for(i=3; i<=NF; i++) {
if (!already[$i])
print $i;
already[$i] = 1
}
}' ~/.bash_history
这会在开头删除可选的sudo调用,然后找到您的apt-get install
调用,并且因为它会轮询您的历史文件而不是history
命令,没有数字(所以虽然早期的答案剥离了四个cols,但我只删除了三个)。这使用awk哈希来删除重复项(保留第一个安装命令的时间顺序)。如果你不关心重复删除,只需省略任何引用已经[$ i]哈希的行(因此for循环中唯一的项是print $i
行)。
仅使用sed
:
sed 's/^sudo//; /^ *apt-get install */!d; s///; s/ */\n/g' ~/.bash_history |sort -u
与awk
解决方案类似,这会剥离可选的sudo
调用并匹配apt-get install
命令。匹配“未删除”(这意味着删除了不匹配),然后匹配部分(“apt-get install”)被替换为空字符串。然后,每个连续的空格字符串将替换为换行符。最后,它全部排序,只显示唯一的输出。请注意,如果不使用sort -u
,我的代码会有一些额外的空白行可能会很烦人。
了解您的实际目标:也许您只是在寻找已安装的软件包?您没有手动将它们全部指定为apt-get install [package]
命令;有些是作为依赖项引入的,有些可能没有进入你的历史文件,因为多个shell不正确地将它们的历史折叠在一起,安装命令可能太旧,或者你可能使用了像Synaptic这样的GUI或其他工具比如aptitude或者这些命令中的一些可能是根历史而不是你的。
也许您只需要一个已安装软件包的列表:
dpkg -l |awk '/^i/ { print $2 }'
也许您只想要最近安装的软件包:
ls -tr /var/cache/apt/archives |sed 's/_.*//g' |sort -u
这实际上显示了您下载的所有内容,包括自上次系统清理该目录以来某些时候待安装的项目。我在-tr
上留下ls
标记,以防您按时间顺序排序(在这种情况下,请删除sort -u
)。请注意,这里的时间顺序是指每个下载的包的时间戳,我认为这与下载时间相对应(尽管可能是在Ubuntu / Debian打包的时间),这应该足够接近。
也许你想对那些仍然安装的东西进行审查(结合上面的两个命令)。首先,保存第一个命令的输出。然后,运行第二个命令并通过第一个命令的输出对其进行过滤:
dpkg -l |awk '/^i/ { print $2 }' >/tmp/installed
ls -tr /var/cache/apt/archives |sed 's/_.*//g' |grep -Fxf /tmp/installed |sort -u
与上面的示例一样,这是为了让您删除sort -u
并按时间顺序排列。它结合了以上两种方法;首先,获取所有已安装软件包的列表并将其存储在/tmp/installed
中,然后列出所有最近下载的软件包,然后仅显示代表仍安装的软件包的下载。 Grep的-f FILE
标志表示FILE中的每一行都是要测试的模式(逻辑OR),而-Fx
标志需要整行的文字匹配(点是一个点)(“foo” “不匹配”foo-dev“)。
答案 1 :(得分:1)
无需grep
。
awk '/^apt-get install/ {for (i = 4; i <= NF; i++) print($i)}'
应列出所有已安装的软件包,每行一个。如果前面有一个sudo
或者apt-get
命令后面有一个标志,这不适用于不规则的间距,但它可以适应所有这一点。
读为:对于每一行,如果以apt-get install
开头,则打印除前三个以外的所有字段(分别为历史编号,apt-get
和install
) 。请注意,字段零是整个输入行。
答案 2 :(得分:0)
另一种方式
awk '/^apt-get install/{$1=$2=$3="";print}'