我有一个基本的查询。我有一个如下字符串:
on one off abcd on two off
我想找出'on'和'off'之间的所有字符串 我期待的结果是'一'和'两'
我相信这可以用sed ..
我尝试使用sed 's/on\(.*\)off/\1/g'
,但这会返回one off abcd on two
答案 0 :(得分:2)
使用sed,我认为最简单的方法是使用两个sed进程:
echo 'on one off abcd on two off' | sed 's/\<on\>[[:space:]]*/\non\n/g; s/[[:space:]]*\<off\>/\noff\n/g' | sed -n '/^on$/,/^off$/ { //!p; }'
one
two
这分为两部分:
sed 's/\<on\>[[:space:]]*/\non\n/g; s/[[:space:]]*\<off\>/\noff\n/g'
将on
和off
置于易于识别的单行和
sed -n '/^on$/,/^off$/ { //!p; }'
只打印它们之间的东西。
或者,您可以使用Perl(支持非贪婪匹配和外观)来实现:
$ echo 'on one off abcd on two off' | perl -pe 's/.*?\bon\b\s*(.*?)\s*\boff\b.*?((?=\bon\b)|$)/\1\n/g; s/\n$//'
one
two
s/.*?\bon\b\s*(.*?)\s*\boff\b.*?((?=\bon\b)|$)/\1\n/g
将所有内容放在\bon\b
和\boff\b
之间(其中\b
匹配字边界)在一行上。主要技巧是.*?
匹配非贪婪,也就是说它匹配找到完整正则表达式匹配所需的最短字符串。 (?=\bon\b)
是零长度前瞻术语,因此.*?
仅在另一个on
分隔符或行尾之前匹配(这是为了丢弃off
之间的数据和on
)。
在
s/\n$//
只删除我们不需要或不想要的最后一个换行符。
答案 1 :(得分:0)
这是awk
版本
awk -v RS=" " '/\<off\>/ {f=0} f; /\<on\>/ {f=1}' file
one
two
答案 2 :(得分:0)
sed 's/\(.*\) off.*/ \1³/;s/ off /³/g;s/ on /²/g;s/³[^²]*²/³²/g;s/^[^²]*²/²/;s/²/\
/g;s/.//;s/³//g'
²
和³
作为分隔符(因为POSIX sed不允许群组拒绝而是类),而不是on
和off
。可以使用字符串中未使用的其他字符(避免使用像&
这样的元字符,...)