sed/awk:从文本流中提取模式

12
2011-07-01 ... /home/todd/logs/server_log_1.log ...
2011-07-02 ... /home/todd/logs/server_log_2.log ...
2011-07-03 ... /home/todd/logs/server_log_3.log ...

我有一个看起来像上面的文件。 我想从中提取文件名并将其输出到 STDOUT 中,如下所示:

server_log_1.log
server_log_2.log
server_log_3.log

能有人帮帮我吗?谢谢!

文件名模式是server_log_xxx.log,且每行只出现一次。


由于文件名可以包含几乎任何字符(空格、换行符、控制字符,在大多数Unix文件系统中,除了'\0''/'之外的任何字符),因此这3行文本可能是一个有效的文件名。除非对有效文件名和两个“...”中出现的内容添加一些限制,否则无法可靠地识别文件名。特别要小心,因为记录未经过消毒的用户控制变量(例如输入、主机名)的日志文件可能成为针对编写不良解析器的注入攻击的目标。 - jw013
jw013:不对,你需要在文件名中加入 '\n',否则这三行就会被视为三个条目。 - Karoly Horvath
@yi '\n' 是文件名中有效的字符。你无法对“所有可能的文件名”进行任何合理的匹配,只是举了一个例子,指出整行或任何线路串联(达到文件系统文件名长度限制)都是一个有效的文件名。现在Todd已经指定了他所寻找的模式,问题变得更加合理了(虽然xx部分仍未指定,但它们可能代表数字)。我真的不明白你说“不”的意思。 - jw013
4个回答

27

假设“xxx”占位符仅为数字:

grep -o 'server_log_[0-9]\+\.log'

9

通过以下命令将您的文件传输:

sed 's/.*\(server_log_[0-9]\+\.log\).*/\1/'

sed 's/.(server_log_[0-9]+.log)./\1/' 更简单,对吧? - Dagang
没错,但需要转义大括号。之前因为我省略了 .* 所以没有起作用。我更新了我的解决方案。 - Paweł Nadolski
这不需要-n参数和p后缀吗?sed -n 's/........./\1/p' 是我的可行解。 - alexei

1

使用 awk 和您的输入模式:

awk 'BEGIN {FS="/"}
     { print gensub(" .*$","","g",$5) }' INPUTFILE

在此处查看它的运行效果:https://ideone.com/kcadh

希望对你有所帮助


0
sed 's|.*/\([^/ ]*\).*|\1|' infile

3
s命令末尾加上p,并且添加-n选项,除非你希望看到每一行不符合模式的结果。 - jw013

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接