用Sed替换多行模式中的一个字符

时间:2014-11-14 02:20:11

标签: regex bash sed

我有一个文件,其布尔值设置为下一行显示的文件位置。我需要更改'删除'对于包含' trash'的所有文件路径,值为1在他们中。我正在尝试使用sed来完成这项任务。

我很难获得模式引用(即。\ 1)以正确输出

请参阅下面的文件示例:

delete: 0
filepath: Downloads/trash/foo1
delete: 0
filepath: Downloads/keep/foobar
delete: 0
filepath: Downloads/trash/foofoofoo

这就是我对sed功能所拥有的。我试图通过\ 1稍后引用第二行作为引用,但它输出为' 1'。

sed -e '
/delete)/{
N
/\(.*trash.*\)/c \
delete: 1
\1
}' test.txt > test2.txt

输出:

delete: 1
1
delete: 0
filepath: Downloads/keep/foo1
delete: 1
2

我看到我想要的两条线都发生了变化,所以我知道我在模式空间中取出了正确的线条。但第二行输出不正确。我也知道这种类型的语法在单行替换中工作正常,但在这种多行情况下不行。

任何帮助将不胜感激。谢谢。

3 个答案:

答案 0 :(得分:2)

这可能适合你(GNU sed):

sed '/^delete/{N;/trash/s/delete: 0/delete: 1/}' file

这会查找以delete开头的行,然后附加下一行并查找trash,如果是,则用delete: 0替换delete: 1

N.B。您不能仅在i中的acs/.../.../命令中使用反向引用 见here

答案 1 :(得分:2)

sed是用于涉及多行的任何问题的错误工具。这就是awk的用途:

$ awk '!(NR%2){print "delete:", (/trash/?1:0) ORS $0}' file
delete: 1
filepath: Downloads/trash/foo1
delete: 0
filepath: Downloads/keep/foobar
delete: 1
filepath: Downloads/trash/foofoofoo

或者由于其他原因,您现有的删除值可能不为零:

$ awk 'NR%2{d=$NF;next} {print "delete:", (/trash/?1:d) ORS $0}' file
delete: 1
filepath: Downloads/trash/foo1
delete: 0
filepath: Downloads/keep/foobar
delete: 1
filepath: Downloads/trash/foofoofoo

答案 2 :(得分:0)

$ sed -i '$!N;s/^delete: 0\(\nfilepath:.*\/trash\/.*\)$/delete 1\1/i;P;D' test.txt
delete 1
filepath: Downloads/trash/foo1
delete: 0
filepath: Downloads/keep/foobar
delete 1
filepath: Downloads/trash/foofoofoo
$