锯这里一种使用 sed 获取一行中其他两个字符串之间的文本的方法,例如:
sed 's/.*starting_text\(.*\)ending_text.*/\1/'
但我想要一个简单的命令(例如tr
,但用于字符串提取),只需两个字符串,并会修剪第一个字符串之前或第二个字符串之后的所有内容,例如
grep something some_file | between message\"\:\" " with"
并会处理转义字符。
答案1
如果分隔符可能每行出现多次,您可以使用 perl 代替,如下所示:
between() {
perl -Tlne 'BEGIN{$b=shift;$e=shift}
print for /\Q$b\E(.*?)\Q$e\E/g' "$@"
}
然后例如:
$ echo "[b]test[e] foo [b]bar[e]" | between '[b]' '[e]'
test
bar
您还可以将其用作:
between BEG END file1 file2...
答案2
通常在 sed 中执行此操作需要在用于查找我找到的子字符串的正则表达式中转义字符这里(注:更多信息这里如果您遇到问题)。
然后,我找到了如何通过管道传输到函数中这里。
将所有这些放在一起到一个我可以在 my 中使用的函数中.bashrc
,看起来像(虽然我不必设置 a 和 b 变量,但它更容易阅读):
between(){
a=$(printf '%s\n' "$1"|sed 's![\*.^$/[]!\\&!g')
b=$(printf '%s\n' "$2"|sed 's![\*.^$/[]!\\&!g')
sed "s/.*$a\(.*\)$b.*/\1/"
}
正如约瑟夫·R.提到的,这个答案展示如何使用 grep -oP 执行类似操作。为了转义 Perl 兼容的正则表达式,我发现这,所以也许以下也可以工作:
between(){
a=$(printf '%s\n' "$1"|sed 's![]\*.^+?(){|$[]!\\&!g')
b=$(printf '%s\n' "$2"|sed 's![]\*.^+?(){|$[]!\\&!g')
grep -oP "(?=$a).*?(?=$b)"
}