您好我正在搜索文件并输出与以下正则表达式匹配的行的值,并删除匹配的文本,我不需要将其输出到文件。这是我目前正在使用的,它输出所需的文本,但多次:
#!/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 :(得分: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
这会使用所需的字符串准备保留空间。对于仅包含所需字符串的行,请附加保留空间并检查当前行是否需要修改。将所需的字符串与保留空间中的相同字符串匹配。如果该线已经出现,则该匹配将失败并且该线可以被忽略。如果该行尚未修改,则从当前行中删除所需的字符串,然后打印该行的前半部分。如果在该行的剩余一半中没有出现任何字符串,则该过程结束并且可以退出。否则,删除字符串的前半部分,并用删除的所需字符串替换保留空间。