如何删除一行中的所有内容,直到一个模式,以及另一个模式之后的所有内容?


17

在以下文件中:

Lorem ipsum dolor坐下来,管教着迷。Ut eu metus id lectusvestibulum ultrices。Maecenas菱形。

我想删除之前consectetuer和之后的所有内容elit

我想要的输出:

consectetuer adipiscing elit.

我怎样才能做到这一点?


2
该命令可以是sed。它也可以是perl,甚至是纯bash。
muru

@manuel如果这些答案之一解决了您的问题,请花一点时间并单击左侧的复选标记以接受。这会将问题标记为已回答,并且是在Stack Exchange网站上表达感谢的方式。
terdon

Answers:


27

我会用sed

sed 's/^.*\(consectetuer.*elit\).*$/\1/' file

解码sed s / find / replace /语法:

  • s/^.*-替换从行(^)的开头开始,后跟任何(.*)直到...
  • \( -启动一个命名块
  • consectetuer.*elit\.-匹配第一个单词,将所有(.*)匹配到您要匹配的最后一个单词(在这种情况下,包括结尾的(转义的)点)
  • \) -结束命名块
  • 将其他所有(.*)匹配到行($)的末尾
  • / -结束替代查找部分
  • \1-替换为之间的名字块\(\)上述
  • / -结束替换

1
好的答案,但是您不需要^或,$因为sed会尝试找到最长的匹配项。另外,您可能已经错过了。之后的点elit\.如果需要可以插入。
asoundmove 2015年

2
@asoundmove“ elit”上的尾随点很好。-眼睛很敏锐!我已经更新了答案,在模式中包含了转义点。你也是正确的^,并$没有必要-我把它们放在那里作为提问者注意(本来)说,他是一个有点初学者的,这可能是在其他情况下很有帮助。
MikeV

我一直会复制粘贴sed解决方案并对其进行破解,以满足我的需求,但是由于有了这个答案,我觉得我现在真的很明白。好的答案
泰勒

7

如果每一行都包含开始模式和结束模式,则最简单的方法是使用grep。不必删除每行的开始和结尾,您只需在两个模式之间输出内容即可。-oGNU中的选项grep仅输出匹配项:

grep -o 'consectetuer.*elit' file

注意:如前所述,这仅在文件中的每一行都可以通过这种方式解析时才有效。再说一次,这是所有典型用例的80%。


1

AWK中有两个for循环:

$ awk '{for(i=1;i<=NF;i++) {if ($i == "consectetuer") beginning=i; if($i== "elit.") ending=i }; for (j=beginning;j<=ending;j++) printf $j" ";printf "\n"   }' file.txt 
consectetuer adipiscing elit.

AWK的gsub:

$ awk '{gsub(/^.*consectetuer/,"consectetuer"); gsub(/elit.*$/,"elit.");print}' file.txt
consectetuer adipiscing elit.

1

一种Perl方式。这基本上与MikeV的sed答案相同:

perl -pe 's/.*(consectetuer.*elit).*./$1/' file

-p手段“将与给定的剧本后,打印每一行-e”。的s/foo/bar/是替换操作符; 它将替换foobar。括号捕获一个模式,让我们在替换中使用它。第一个捕获的模式是$1,第二个捕获的模式,$2依此类推。

因此,这个命令将匹配一切都交给consectetuer.*consectetuer),那么一切直到elit.*elit),然后一切,直到行(结束.*),将取代与摄像图案。


1

我不确定为什么这个问题标题已经被“ 从文件 ” 编辑为“ 从一行 ”,而OP并没有排除跨多行的可能性,即使该示例似乎只是一行。无论如何,在此处提供多行解决方案可能会有所帮助。

这适用于交叉线:

from1=consectetuer; to2=elit; a="$(cat file)"; a="$(echo "${a#*"$from1"}")"; echo "$from1${a%%"$to2"*}$to2"

例子:

[xiaobai@xiaobai tmp]$ cat file
1
abc consectetuer lsl

home

def elit dd
2 consectetuer ABC elit
[xiaobai@xiaobai tmp]$ from1=consectetuer; to2=elit; a="$(cat file)"; a="$(echo "${a#*"$from1"}")"; echo "$from1${a%%"$to2"*}$to2"
consectetuer lsl

home

def elit
[xiaobai@xiaobai tmp]$ 

参考:Shell参数扩展


1
那很完美!
克莱门特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.