我基本上正在使用正则表达式。在输出中,我想只看到与我的reg exp匹配的字符串。
在一堆XML文件中(大多数是一行中包含大量数据的单行文件),我想得到所有以 MAIL _ 开头的单词。
另外,我希望shell上的grep命令只给出匹配的单词,而不是整行(在这种情况下是整个文件)。
我该怎么做?
我试过了
grep -Gril MAIL_* .
grep -Grio MAIL_* .
grep -Gro MAIL_* .
答案 0 :(得分:16)
首先,使用随Ubuntu安装的GNU grep,-G标志(使用基本regexp)是默认值,因此您可以省略它,但更好的是,使用带-E的扩展正则表达式。
-r标志表示在目录文件中进行递归搜索,这就是您所需要的。
而且,使用-o标志打印一行的匹配部分是正确的。另外,要省略文件名,您需要一个-h标志。
你犯的唯一错误就是正则表达式本身。你错过了*之前的字符规范。您的命令应如下所示:
grep -Ehro 'MAIL_[^[:space:]]*' .
示例输出(不递归):
$ echo "Some garbage MAIL_OPTION comes MAIL_VALUE here" | grep -Eho 'MAIL_[^[:space:]]*'
MAIL_OPTION
MAIL_VALUE
答案 1 :(得分:6)
尝试以下命令
grep -Eo 'MAIL_[[:alnum:]_]*'
答案 2 :(得分:2)
grep -o or --only-matching
只输出匹配的文本而不是完整的行,但问题可能是你的正则表达不是限制性或贪婪,实际上匹配整个文件。
答案 3 :(得分:0)
从您的评论到Thor的回答,似乎您还想区分MAIL_.*
文本是文本节点还是属性,而不仅仅是在XML文档中出现时将其隔离。 Grep无法解析XML you need a proper XML parser for that。
命令行xml解析器是xmlstarlet。它打包在Ubuntu中。
在此示例文件示例文件中使用它:
$ cat test.xml
<some_root>
<test a="MAIL_as_attribute">will be printed if you want matching attributes</test>
<bar>MAIL_as_text will be printed if you want matching text nodes</bar>
<MAIL_will_not_be_printed>abc</MAIL_will_not_be_printed>
</some_root>
要选择文本节点,您可以使用:
$ xmlstarlet sel -t -m '//*' -v 'text()' -n test.xml | grep -Eo 'MAIL_[^[:space:]]*'
MAIL_as_text
选择属性:
$ xmlstarlet sel -t -m '//*[@*]' -v '@*' -n test.xml | grep -Eo 'MAIL_[^[:space:]]*'
MAIL_as_attribute
简要说明:
//*
是一个XPath表达式,用于选择文档中的所有元素,text()
输出其子文本节点的值,因此除了文本节点之外的所有内容都会被过滤掉//*[@*]
是一个XPath表达式,用于选择文档中的所有属性,然后@*
输出其值