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

Find string between char in unix

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

on one off abcd on two off

我想找出'on'和'off'之间的所有字符串 我在这里期待的结果是 'one' 和 'two'

我相信这可以通过 sed..

我试过 sed 's/on\(.*\)off//g' 但是这个 returns one off abcd on two

对于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)|$)/\n/g; s/\n$//'
one
two

哪里

s/.*?\bon\b\s*(.*?)\s*\boff\b.*?((?=\bon\b)|$)/\n/g

\bon\b\boff\b 之间的所有内容(其中 \b 匹配单词边界)放在一行中。主要技巧是 .*? 非贪婪地匹配,也就是说它匹配找到完整正则表达式匹配项所需的最短字符串。 (?=\bon\b) 是零长度先行项,因此 .*? 仅在另一个 on 定界符或行尾之前匹配(这是丢弃 off 之间的数据和 on).

s/\n$//

只是删除我们不需要或不想要的最后一个换行符。

这是一个awk版本

awk -v RS=" " '/\<off\>/ {f=0} f; /\<on\>/ {f=1}' file
one
two
sed 's/\(.*\) off.*/ ³/;s/ off /³/g;s/ on /²/g;s/³[^²]*²/³²/g;s/^[^²]*²/²/;s/²/\
/g;s/.//;s/³//g'
  • 使用 ²³ 作为分隔符(因为 POSIX sed 不允许组拒绝但 class)而不是 onoff。可以使用字符串中未使用的其他字符(可能避免元字符,如 &、...)
  • 其他操作是分离外部内容(删除)并重新格式化