在unix中查找char之间的字符串

时间:2015-03-20 10:18:32

标签: unix sed

我有一个基本的查询。我有一个如下字符串:

on one off abcd on two off

我想找出'on'和'off'之间的所有字符串 我期待的结果是'一'和'两'

我相信这可以用sed ..

我尝试使用sed 's/on\(.*\)off/\1/g',但这会返回one off abcd on two

3 个答案:

答案 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'

onoff置于易于识别的单行和

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不允许群组拒绝而是类),而不是onoff。可以使用字符串中未使用的其他字符(避免使用像&这样的元字符,...)
  • 其他操作是分隔外部内容(删除)和重新格式化