使用多个sed命令

时间:2014-02-08 00:00:12

标签: regex shell unix sed sh

您好我正在搜索文件并输出与以下正则表达式匹配的行的值,并删除匹配的文本,我不需要将其输出到文件。这是我目前正在使用的,它输出所需的文本,但多次:

#!/bin/sh

for file in *; do
sed -e 's/^owner //g;p;!d ; s/^admin //g;p;!d ; s/^loc //g;p;!d ; s/^ser //g;p;!d' $file
done

首选格式是这样的,所以我可以控制中间发生的事情:

for file in *; do
    sed 's/^owner //g;p' $file | head -1
    sed 's/^admin //g;p' $file | head -1
    sed '/^loc //g;p' $file | head -1
    sed '/^ser //g;p' $file | head -1
done

示例输入文件如下:

owner sys group
admin guy
loc Q-30934
ser 18r9723
comment noisy fan is something

,所需的输出如下:

sys group
guy
Q-30934
18r9723

3 个答案:

答案 0 :(得分:1)

您多次给sed p(用于打印)命令。它每次都打印整行。除非您使用-n选项告诉它,否则sed无论如何都会在最后打印该行。

您还多次提供!d命令。

添加多个sed版本后编辑:不使用head -q,而只使用-n来避免打印您不想要的行。或者甚至可以在打印您想要的位后使用q(退出)停止处理。

例如:

sed -n '/^owner / { s///gp; q; }' $file

{}将替换和退出命令组合在一起,以便当且仅当模式匹配时才执行它们。在开头的地址中使用了模式后,您可以将其从s命令中删除。所以这个命令很简短:

sed -n '/^owner / { s/^owner //gp; q; }' $file

答案 1 :(得分:1)

我建议:

sed -n -e '/^owner / { s///; p; }' \
       -e '/^admin / { s///; p; }' \
       -e '/^loc /   { s///; p; }' \
       -e '/^ser /   { s///; p; }' \
    *

sed完全能够读取许多文件,因此不需要循环控制(例如,您不进行每个文件的I / O重定向),并且在其余部分之后列出文件是合理的。 sed命令(本身就是*)。如果你有一个更现代的sed版本(例如GNU sed),你可以将这些模式组合成一行:

sed -r -n -e '/^(owner|admin|loc|ser) / { s///; p; }' *

答案 2 :(得分:1)

这可能适用于(GNU sed):

sed '0,/^owner /{//s///p};0,/^admin /{//s///p};0,/^loc /{//s///p};0,/^ser /{//s///p}' file

创建一系列切换开关,每个切换开关用于一个所需的字符串。对于每个字符串,开关仅在整个文件中应用一次,即仅打印每个字符串的第一个出现。

替代方案并且取决于文件大小可能更快的方法:

sed -rn '1{x;s/^/owner admin loc ser /;x};/^(owner |admin |loc |ser )/{G;/^(owner |admin |loc |ser )(.*\n.*)\1/!b;s//\2/;P;/\n$/q;s/.*\n//;h}' file

这会使用所需的字符串准备保留空间。对于仅包含所需字符串的行,请附加保留空间并检查当前行是否需要修改。将所需的字符串与保留空间中的相同字符串匹配。如果该线已经出现,则该匹配将失败并且该线可以被忽略。如果该行尚未修改,则从当前行中删除所需的字符串,然后打印该行的前半部分。如果在该行的剩余一半中没有出现任何字符串,则该过程结束并且可以退出。否则,删除字符串的前半部分,并用删除的所需字符串替换保留空间。