2014-02-08 121 views
0

嗨我正在寻找通过文件进行搜索,并输出与下面的正则表达式相匹配的行的值与删除匹配的文本,我不需要它输出到一个文件。这是我目前使用的,它是输出所需的文本,但多次:使用多个sed命令

#!/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 

回答

0

您正在给sedp(用于打印)命令几次。它每次打印整行。除非您告知不要使用-n选项,否则sed将在最后打印该行。

您还多次给出!d命令。

在添加多版本版本后进行编辑:而不是使用head -q,只需使用-n即可避免打印您不想要的行。甚至使用q(退出)在打印完您想要的位后停止处理。

例如:

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

{}组的取代和退出命令一起,使它们都执行当且仅当所述模式匹配。在开始使用地址模式后,您可以将其保留在s命令之外。因此,该命令是短期的:

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

感谢您的回答,我试过这个:sed's/^ owner // g; q'$ file,它在第一个sed命令之后工作,但之后的sed命令只输出文件的第一行而不合并 –

+0

这几乎是正确的。我已经为我的答案添加了一个示例。编辑完成后,它会在一两分钟后出现。简而言之,s和q命令是独立的,所以q在第一行执行。你需要用括号将它们组合在一起。 –

+0

非常感谢你! –

0

我建议:

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; }' * 
+0

不幸的是,这会导致误报,因为每个文件可能有不止一次出现所需的字符串。 – potong

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 

此制备物与所需的字符串保留空间。对于只包含所需字符串的行,追加保留空间并检查当前行是否需要修改。将所需的字符串与保存空间中的相同字符串进行匹配。如果该线已经出现,则该比赛将失败并且该线可以被忽略。如果该行尚未修改,则将从当前行中删除所需的字符串,然后打印行的前半部分。如果在剩下的一半行中没有字符串出现,则该过程结束并可以退出。否则,请移除字符串的前半部分,并用所需的字符串替换保留空间。