用 3 行滑动窗口替代 sed

用 3 行滑动窗口替代 sed

我需要使用 Sed 实现一个 3 行滑动窗口,以便更改大文本文件中出现的以下 3 行分组:

Fax: 05.11.22.33.44<LF>
<LF>
<LF>

有了这个 :

Fax: 05.11.22.33.44<LF>
###
<LF>

我尝试使用以下命令行来执行此操作(sed 在 msdos 批处理文件中运行,但它在我的 linux bash 下也不起作用):

sed -i ":a;$!N;s/\nFax: \([ 0-9\.]*\n\n\);tenough;$!ba;:enough/\nFax: \1###\n/;$!ba;P;D" file.txt

怎么了 ?

答案1

你猜P;D对了。剩下的就是在模式空间中拉线的失败尝试,直到替换成功,这不一定是坏事,但绝对不是滑动窗口。
您应该在第一行时拉入一行,然后使用N;P;D循环(这样你在模式空间中总是有三行)并尝试在每次拉入新行时进行替换

sed '1N;$!N;s/\(PATTERN\n\)\(\n\)$/\1###\2/;P;D' infile

答案2

思考这接近您最初尝试的实现:

sed ':a; $q; N; s/\(Fax:.*\n\)\n$/\1###\n/; 3,${P;D}; ba'

前任。

$ sed ':a; $q; N; s/\(Fax:.*\n\)\n$/\1###\n/; 3,${P;D}; ba' input > output
$ diff -y input output
Fax: 05.11.22.33.44                                             Fax: 05.11.22.33.44
Fax: 05.11.22.33.44                                             Fax: 05.11.22.33.44

Fax: 05.11.22.33.44                                             Fax: 05.11.22.33.44
                                                              | ###

Fax: 05.11.22.33.44                                             Fax: 05.11.22.33.44
Fax: 05.11.22.33.44                                             Fax: 05.11.22.33.44
                                                              | ###

Fax: 05.11.22.33.44                                             Fax: 05.11.22.33.44

诀窍在于3,${P;D},这就是维持 3 行窗口的原因(通过每次循环从模式空间中弹出一行,但仅在行数达到 3 后)。

答案3

Steeldriver 的解决方案有一个优势:它可以跨 5 条生产线工作,也可以跨 7 条或更多生产线工作。在我的例子中:找到匹配的行,并用该行的第一部分替换前面的两行、匹配的行和后面的两行,然后用空的“List”值代替现有的值。

输入被删节,行最初> 2000长:

Frame 64 (List 213 [(LM 0 0 836 216 112 0.681952 0.260603)])
Frame 65 (List 236 [(LM 0 0 836 216 112 0.680071 0.187739)])
Frame 66 (List 235 [(LM 0 0 836 216 112 0.678168 0.315848)])
Frame 67 (List 98 [(LM 149 129 1456 216 112 0.525970 11.970105)])
Frame 68 (List 217 [(LM 0 4 1084 216 112 0.837058 0.658243)])
Frame 69 (List 212 [(LM 0 0 1084 216 112 0.829624 0.339764)])
Frame 70 (List 218 [(LM 0 0 1084 216 112 0.829624 0.200893)])

匹配第 67 行(不正常值)的 Sed 命令是:

sed -re ":a; $q; N; s/(Frame .[0-9] ).*(Frame .[0-9] ).*(Frame .[0-9] ).*LM\ [0-9][0-9][0-9].*(Frame .[0-9] ).*(Frame .[0-9] ).*/\1(List 0 \[\]\)\n\2\(List 0 \[\]\)\n\3\(List 0 \[\]\)\n\4\(List 0 \[\]\)\n\5\(List 0 \[\]\)/; 5,${P;D}; ba" transform1.trf > transform2.trf

sed 命令匹配第 67 帧,输出为:

Frame 64 (List 213 [(LM 0 0 836 216 112 0.681952 0.260603) <cut>])
Frame 65 (List 0 [])
Frame 66 (List 0 [])
Frame 67 (List 0 [])
Frame 68 (List 0 [])
Frame 69 (List 0 [])
Frame 70 (List 218 [(LM 0 0 1084 216 112 0.829624 0.200893) <cut>])

看这里https://trac.ffmpeg.org/ticket/6816为什么我搜索这个。我没有足够的声誉来将其发布为评论,或对解决方案进行投票,所以我以这种方式发布。其他人也许能够使用它。所以我要感谢 Steeldriver。

相关内容