![如何从一行中删除一个模式之前的所有内容以及另一个模式之后的所有内容?](https://linux22.com/image/77486/%E5%A6%82%E4%BD%95%E4%BB%8E%E4%B8%80%E8%A1%8C%E4%B8%AD%E5%88%A0%E9%99%A4%E4%B8%80%E4%B8%AA%E6%A8%A1%E5%BC%8F%E4%B9%8B%E5%89%8D%E7%9A%84%E6%89%80%E6%9C%89%E5%86%85%E5%AE%B9%E4%BB%A5%E5%8F%8A%E5%8F%A6%E4%B8%80%E4%B8%AA%E6%A8%A1%E5%BC%8F%E4%B9%8B%E5%90%8E%E7%9A%84%E6%89%80%E6%9C%89%E5%86%85%E5%AE%B9%EF%BC%9F.png)
在以下文件中:
Lorem ipsum dolor 坐在 amet,consectetuer adipiscing elit。 Ut eu metus id lectus 前庭 ultrices。梅塞纳斯·隆克斯。
我想删除之前consectetuer
和之后的所有内容elit
。
我想要的输出:
consectetuer adipiscing elit.
我怎样才能做到这一点?
答案1
我会使用 sed
sed 's/^.*\(consectetuer.*elit\).*$/\1/' file
解码 sed s/find/replace/ 语法:
s/^.*
-- 替换从行首 (^
) 开始,后跟任何内容 (.*
) 直到...\(
- 启动一个命名块consectetuer.*elit\.
- 匹配第一个单词,所有 (.*
) 到最后一个单词(在本例中,包括尾随(转义)点)要匹配\)
- 结束命名块- 将其他所有内容 (
.*
) 与行尾 ($
)匹配 /
- 结束替代查找部分\1
\(
- 替换为上面和\)
上面之间的名称块/
- 结束替换
答案2
如果每行包含开始和结束模式,那么最简单的方法是使用grep
.代替删除每行的开头和结尾,您可以简单地输出两种模式之间的内容。-o
GNU 中的选项仅grep
输出匹配项:
grep -o 'consectetuer.*elit' file
注意:如上所述,只有当文件中的每一行都可以这样解析时,这才有效。话又说回来,这占所有典型用例的 80%。
答案3
我不确定为什么这个问题标题已被编辑“从文件“ 到 ”从一条线”虽然OP并不排除跨多行的可能性,即使示例似乎只有一行。无论如何,在这里提供多行解决方案可能会有所帮助。
这适用于交叉线(from1
如果且to2
存在于文件中,则此答案有效。):
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]$
参考:外壳参数扩展
答案4
一种 Perl 方式。这本质上是相同的迈克V的sed
回答:
perl -pe 's/.*(consectetuer.*elit).*./$1/' file
意思-p
是“在应用给定的脚本后打印每一行-e
”。是s/foo/bar/
替换运算符;它将替换foo
为bar
.括号捕获了一个模式,让我们在替换中使用它。第一个捕获的模式是$1
,第二个$2
,依此类推。
因此,该命令将匹配consectetuer
( .*consectetuer
) 之前的所有内容,然后是elit
( .*elit
) 之前的所有内容,然后是行尾 ( .*
) 之前的所有内容,并将其替换为捕获的模式。