使用“grep”系列中的一个。如何获取省略搜索词的行?

时间:2014-02-23 17:29:21

标签: linux command-line sed awk grep

解释

我想从Linux历史记录命令中获取所有行apt-get install,但是我想要列出已安装的内容我还希望将这些行加入其中并删除apt-get install从中。稍后将使用它来创建在另一台计算机上安装相同软件包的命令。 只能使用我必须与awk, sed etc结合的一个greps吗?

3 个答案:

答案 0 :(得分:4)

只有grep(因为你问过):

grep -Pow '^\s*(?:sudo\s+)?apt-get\s+install\s+\K.*' ~/.bash_history \
  |grep -Eow '\S+' |sort -u

这会过滤apt-get install命令的历史记录文件,并在安装后显示这些命令的一部分(\Kgrep -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-getinstall) 。请注意,字段零是整个输入行。

答案 2 :(得分:0)

另一种方式

awk '/^apt-get install/{$1=$2=$3="";print}'