我想显示文件中字符串“xxx”和“yyy”之间的所有字符(引号不是分隔符的一部分)。我怎样才能做到这一点 ?例如,如果我输入“Hello world xxx 这是一个文件 yyy”,则输出应该是“这是一个文件”
答案1
答案2
这应该做你想做的事:
sed -e 's/xxx\(.*\)yyy/\1/'
这假设两个分隔符字符串位于同一行
答案3
仅当分隔符不一定位于同一行时,这个问题才有意义。它可以通过多种方式完成(甚至使用sed
),但awk
更灵活:
#!/bin/sh awk' 开始{发现=0; } /xxx/ { 如果(!找到){ 发现=1; $0 = substr($0, 索引($0, "xxx") + 3); } } /yyy/ { 如果(找到){ 发现=2; $0 = substr($0, 0, 索引($0, "yyy") - 1); } } { 如果(找到){ 打印; 如果(找到==2) 发现=0; } } '
对于一行中最多有一个子字符串的情况,使用以下数据进行了简单测试:
这是 xxx yy 第一的 第二年 xxx.x yyy xxx#yyy
和这个输出(脚本是“foo”,数据是“foo.in”):
$ cat foo.in|./foo yy 第一的 第二 。X #
它的工作方式是,输入数据位于 中$0
,并且 awk 按顺序匹配模式xxx
和,从而允许在到达最后一步(即打印数据)的过程中yyy
更改多个内容。$0
顺便说一句,这个例子不适用于
xxxxHelloyyyxxxWorldyyy
因为它只检查第一个匹配项。 Perl 脚本将给出不同的结果,因为它使用贪婪匹配而不是我在 awk 示例中使用的索引/子字符串。当然,Perl 也可以用脚本来做同样的事情。
Awk(像 Perl)是自由格式的,因此可以将命令表达为类似
awk 'BEGIN{found=0;}/xxx/{if(!found){found=1;$0=substr($0,index($0, "xxx")+3);}}/yyy/{if(found){found=2;$0=substr($0,0,index($0,"yyy")-1);}}{ if(found){print;if(found==2)found=0;}}'
但除非是为了举例,否则很少这样做。同样,sed
脚本(面向行)可以组合成一行,但有一些限制。同样,复杂的脚本sed
很少以这种方式处理。相反,它们被视为真实的程序(参见例子)。
进一步阅读:
答案4
xxx
当和yyy
不在同一行时 也适用的解决方案:
cat /tmp/xxx-to-yyy| perl -ne '(/xxx/../yyy/) && print' | perl -pe 's/.*(xxx.*)/$1/' | perl -pe 's/(.*yyy).*/$1/'
不太漂亮...
切换-e
到perl
只是在命令行上给出脚本。 and-n
使其-p
在输入行上循环,-p
它们在脚本之后打印,但-n
它们不是。所以基本上这只是通过三个 perl 循环发送文件。
..
是一个范围运算符,在左侧条件返回 true 之前返回 false,在右侧条件返回 true 后返回 false,因此第一个循环将文件截断到两个字符串之间的行(两者都包含在内。最后两个 perl 命令删除了之前xxx
和之后的文本yyy
。