如何使用sed/grep提取两个单词之间的文本?
如何使用sed/grep提取两个单词之间的文本?
这个问题的原因是,接受的答案没有删除Here
之前或String
之后的文本。以下解决方法可以解决这个问题:
sed -e 's/.*Here\(.*\)String.*/\1/'
主要区别是在Here
之前和String
之后添加了.*
。
你的答案很有希望。不过有一个问题,如果同一行中有多个String
,我该如何提取到第一个出现的String
?谢谢。
你需要将*
量词设置为非贪婪模式(lazy),即在Here
和String
之间。然而,sed使用的正则表达式类型不支持懒惰量词(?
紧跟在.*
之后),根据这个Stackoverflow问题。通常,要实现懒惰量词,你只需要匹配除了你不想匹配的标记之外的所有内容,但在这种情况下,不仅仅是一个单个标记,而是一个完整的字符串String
。
谢谢,我使用awk得到了答案,stackoverflow.com/questions/51041463/…
不幸的是,如果字符串中有换行符,这个方法不起作用。
这是正常的。点.
不匹配换行符。如果你想匹配换行符,你可以将.
替换为例如[\s\s]
。
将.
替换为[\s\s]
不会删除换行符。
糟糕,应该是[\s\S]
。
sed和grep是在Unix/Linux系统中常用的文本处理工具。有时候我们需要从一段文本中提取出某两个关键词之间的内容,这时就可以使用sed或者grep来完成。
在这个问题中,用户想要从字符串"Here is a one is a String"中提取出"one is"和"String"之间的内容。最初的解决方法是使用sed命令:sed -e 's/one is\(.*\)String/\1/'
。然而,这个命令会同时提取出"Here is a",而不仅仅是"one is"和"String"之间的内容。
为了只提取出"one is"和"String"之间的内容,用户需要修改正则表达式,使其匹配整行文本。修正后的命令是:sed -e 's/.*one is\(.*\)String.*/\1/'
。在sed中,s/pattern/replacement/
的意思是"在每一行上将'pattern'替换为'replacement'"。只有匹配到"pattern"的部分才会被替换,所以如果想要替换整行文本,就需要让"pattern"匹配整行。
然而,这个解决方法在输入为"Here is a String Here is a String"的情况下会出现问题。为了解决这个问题,用户提出了一个新的需求:只提取出第一个"Here"和"String"之间的内容。正则表达式不支持非贪婪匹配,所以无法直接实现这个需求。用户在问题中提供了一个链接,其中有一些推荐的替代方案。
用户在这个问题中遇到了提取两个关键词之间内容的需求,最初使用的命令无法完全满足需求,后来通过修改正则表达式实现了只提取关键词之间内容的目标。然而,在处理特定的输入情况时,用户发现了解决方案的局限性,需要寻找替代方案来满足新的需求。
如何使用sed/grep提取两个单词之间的文本?
问题的原因是,有时我们需要从文本中提取两个特定单词之间的内容。在这种情况下,我们可以使用sed或grep命令来实现。下面是解决此问题的方法:
对于grep命令,可以使用正向和负向前瞻和后顾来提取文本。对于这个问题,命令如下:
echo "Here is a string" | grep -o -P '(?<=Here).*(?=string)'
如果存在多个“Here”和“string”的出现,您可以选择是否要从第一个“Here”和最后一个“string”进行匹配,或者单独匹配它们。在正则表达式中,这被称为贪婪匹配(第一种情况)或非贪婪匹配(第二种情况)。
$ echo 'Here is a string, and Here is another string.' | grep -oP '(?<=Here).*(?=string)' # 贪婪匹配 is a string, and Here is another $ echo 'Here is a string, and Here is another string.' | grep -oP '(?<=Here).*?(?=string)' # 非贪婪匹配 is a is another
请注意,GNU grep的-P选项在包括*BSD在内的grep中不存在,或者在任何SVR4(Solaris等)中提供的grep中也不存在。在FreeBSD中,您可以安装包含pcregrep的devel/pcre端口,该端口支持PCRE(以及前瞻/后顾)。OSX的旧版本使用GNU grep,但在OSX Mavericks中,-P派生自FreeBSD的版本,不包括该选项。
如果您的结束字符串“string”出现多次,上述方法将获取最后一次出现的内容,而不是下一次出现的内容。
对于这种情况,您可以使用以下命令:
echo "Here is a string a string" | grep -o -P '(?<=Here).*?(?=string)'
请注意,grep的-P标志在MacOS X 10.9及以上版本中不起作用。但您可以按照这个指南将其转换为perl命令。
对于处理XML文件,应避免使用文本操作命令(如awk、sed)进行解析。而应该使用xmlstarlet。不过,您仍然可以像处理其他文本文件一样使用sed/awk处理XML。
如果要在结果中包含“Here”和“string”,可以使用以下命令:
grep -o 'Here.*string' 或者 grep -oP 'Here.*?string'
如果两个模式位于不同的行上,您需要启用pcregrep的多行搜索功能。可以使用以下命令:
echo $'Here is \na string' | grep -zoP '(?<=Here)(?s).*(?=string)'
如果只想在第一个匹配处停止,可以使用一些简单的技巧。将输入和搜索字符串颠倒,执行非贪婪搜索并颠倒结果。可以使用rev命令来实现。
如果希望从最后一个“Here”和“string”之间捕获文本,可以使用sed或perl命令:
perl -nE 'say /.*(?<=Here)(.*)String/' 或 sed -r 's/.*Here(.*)String/\1/'
以上就是使用sed/grep提取两个单词之间文本的方法。