Sed语法 - 分解

时间:2012-08-11 07:49:56

标签: bash sed

我想知道是否有人可以帮我理解以下命令。这个命令的目的是清除旧内核,但我想理解语法:

dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d' | xargs sudo apt-get -y purge

这是我到目前为止所做的:

dpkg -l'linux - *' - 列表包含“linux - *”模式

sed'/ ^ ii /!d; /'... - 找到以 ii 开头的行,但不包含 d;

“$(uname -r | sed”s /(.*)-([^ 0-9] +)/ \ 1 /“)”'/ d - 命令替换列表当前内核只提取版本中的数字, sed“s /(.*)... - 搜索任意数量的字符, ...([^ 0-9 ] ...... - 从数字0-9开始,我不明白这一点: ... +)/ \ 1 /...

我完全迷失了这个:

s / ^ [^] * [^] *([^] )。 / \ 1 /; / [0-9] /!d' - 是在寻找开始字符串的空字符吗?

此致

1 个答案:

答案 0 :(得分:2)

所以,我们在这里有一个很长的sed命令来分析:

'/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d'

它提供了一个与dpkg语法中的'linux- *'匹配的软件包列表,这一点有点神秘,但行的开头表示有关软件包状态的信息。

sed命令本身很长(虽然我犯了更糟糕的错误!),但相当简单,没有循环或并发症。正如精细手册所告诉你的那样,sed接受程序作为由分号分隔的命令列表。因此,给定的sed程序有四个命令。

首先,'/ ^ ii /!d'。我们删除不以'ii'开头的行。很简单。我们正在寻找要删除的已安装软件包。

其次,'/'“$(uname -r | sed”s /(.*)-([^ 0-9] +)/ \ 1 /“)”'/ d'。这是命令行中的命令行(使用bash的$()语法),因此我们将从内到外工作。目的显然是从我们当前运行的内核的包列表中过滤掉,因此我们不会将其删除。 uname -r的输出与debian软件包名称不完全匹配,因此它从“3.0.0-generic”过滤到“3.0.0”。内部sed命令,“s /(.*)-([^ 0-9] +)/ \ 1 /”)“,只是一个简单的正则表达式搜索和替换,切断了结束任何连字符后的输入。在$()替换之后,外部sed命令看起来像'/3.0.0/d'(取决于你正在运行的内核)。它只删除包含你当前的行内核版本号。

第三和第四,'s / ^ [^] * [^] *([^] )。 / \ 1 /'和'/ [0-9] /!d'是最后的过滤器。第一个是基本的搜索和替换(在awk中会更清楚地完成)提取行的第三个字段,它将是包名称,之后我们删除哪些行不包含数字(否则我们会删除引入内核升级的元数据包)。

最后,xargs逐行获取其输入并运行您在每一行传递的命令,并在其参数后附加该行。因此,我们删除了我们找到的每个包。