我一直在尝试从一个巨大的文件中提取表单数据。我需要一个非常具体的模式,但到目前为止我还是失败了。
我有日志的一致部分:
Machine info and user info blah blah blah [senderID=60,
ipaddress=/10.1.1.11:8443, serviceIdinList=[13], serviceBitbox=11111,
servicesList= | BeatController | BeatMaker | WaveShow, client=apache,
所有行都像这样显示。
从这一行我需要使它看起来像这样:
senderID=60, ipaddress=/10.1.1.11:8443, serviceIdinList=[13],
serviceBitbox=11111, servicesList= | BeatController | BeatMaker | WaveShow,
*注意,“WaveShow”之后的所有内容都是无关紧要的,“senderID”之前的所有内容也是如此
我已经从这里的帖子中尝试过这个命令,
sed -n '/servicesList=/{s/.*servicesList=//;s/\S*=.*//;p}'
但它只打印出来
servicesList= | BeatController | BeatMaker | WaveShow
我尝试使用正则表达式在一些迭代中修改它,使用 grep 和 sed 但没有进展
答案1
如果您想要做的是输出 和 之间的所有内容(包括senderID=
和 )WaveShow,
,那么您需要以下sed
命令:
sed -n 's/.*\(senderID=.*WaveShow,\).*/\1/p'
这将使用\(
和\)
括号捕获这两个字符串之间的所有内容,并使用\1
(\2
等等,如果您有更多捕获)输出它。
请注意,前导.*
是“贪婪的”,这意味着如果输入中出现senderID=
两次该字符串,则第一个将被丢弃。如果这不是您想要的,那么sed
这不是正确的工具;perl
可以处理这个。命令则变为:
perl -ne 'print if s/.*?(senderID=.*WaveShow,).*/$1/'
-n
意思是“对每一行输入执行一个循环,并且不在循环末尾打印该行”。-e
指定要在循环内执行的表达式。
?
更改后尽可能少地匹配(即非贪婪地匹配).*
。*
括号使 perl 对该部分进行分组并捕获它,然后可以将其用作$1
第一次捕获、$2
第二次捕获等。
然而,这不是在 Perl 中执行此操作的最佳方式。这要好得多,因为它不涉及不必要地更改字符串、捕获文本并打印:
perl -ne 'print "$1\n" if /(senderID=.*WaveShow,)/'
在 Perl 中可能有更多的方法可以做到这一点,甚至可能更有效。
答案2
结尾的逗号是必需的吗?
如果没有,这应该有效:
grep senderID filename | cut -d '[' -f 2- | cut -d ',' -f -5
输出:
senderID=60, ipaddress=/10.1.1.11:8443, serviceIdinList=[13], serviceBitbox=11111, servicesList= | BeatController | BeatMaker | WaveShow