如何使用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与-P
( perl-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
。