如何使用sed / grep来提取两个单词之间的文本?

我试图输出一个string,其中包含一个string的两个单词之间的所有内容:

input:

"Here is a String" 

输出:

 "is a" 

使用:

 sed -n '/Here/,/String/p' 

包括端点,但我不想包括它们。

 sed -e 's/Here\(.*\)String/\1/' 

简单的grep也可以支持正面和负面的预见和回顾:对于你的情况,命令是:

  echo "Here is a string" | grep -o -P '(?<=Here).*(?=string)' 

你可以单独在Bash中去掉string:

 $ foo="Here is a String" $ foo=${foo##*Here } $ echo "$foo" is a String $ foo=${foo%% String*} $ echo "$foo" is a $ 

如果你有一个包含PCRE的GNU grep,你可以使用一个零宽度的断言:

 $ echo "Here is a String" | grep -Po '(?<=(Here )).*(?= String)' is a 

如果你有一个很长的文件,有很多多行选项,首先打印数字行是很有用的:

 cat -n file | sed -n '/Here/,/String/p' 

通过GNU awk,

 $ echo "Here is a string" | awk -v FS="(Here|string)" '{print $2}' is a 

grep与-Pperl-regexp )参数支持\K ,这有助于丢弃以前匹配的字符。 在我们的例子中,之前匹配的string是Here所以它从最终的输出中被丢弃。

 $ echo "Here is a string" | grep -oP 'Here\K.*(?=string)' is a $ echo "Here is a string" | grep -oP 'Here\K(?:(?!string).)*' is a 

如果你想输出is a然后你可以尝试下面,

 $ echo "Here is a string" | grep -oP 'Here\s*\K.*(?=\s+string)' is a $ echo "Here is a string" | grep -oP 'Here\s*\K(?:(?!\s+string).)*' is a 

接受的答案不会删除String之前或之后的文本。 这会:

 sed -e 's/.*Here\(.*\)String.*/\1/' 

主要区别在于.*之前和之后加上.*

这可能适用于你(GNU sed):

 sed '/Here/!d;s//&\n/;s/.*\n//;:a;/String/bb;$!{n;ba};:b;s//\n&/;P;D' file 

这将在换行符的两个标记(本例中为“ Here和“ String )之间显示文本的每个表示forms,并在文本内保留换行符。

上述所有的解决scheme都有缺陷,最后的searchstring在string中的其他地方重复。 我发现最好写一个bash函数。

  function str_str { local str str="${1#*${2}}" str="${str%%$3*}" echo -n "$str" } # test it ... mystr="this is a string" str_str "$mystr" "this " " string" 

您可以使用\1 (请参阅http://www.grymoire.com/Unix/Sed.html#uh-4 ):

 echo "Hello is a String" | sed 's/Hello\(.*\)String/\1/g' 

括号内的内容将被存储为\1