Regex sed:跨多行截断长条目

Regex sed:跨多行截断长条目,regex,sed,Regex,Sed,首先,我有一个我认为可行的解决方案。然而,测试用例 是一回事…现实并不总是那么美好。这是一个“这看起来对吗?” 问题…或者,更好的是,“这会在哪里失败?建议改进?”问题 问题: 标题不应超过一行 测试文件: You have a hold available for pickup as of 2012-01-13: Title: Really Long Test Title Regarding Random Gibberish. Volume 1, A-B, United States an

首先,我有一个我认为可行的解决方案。然而,测试用例 是一回事…现实并不总是那么美好。这是一个“这看起来对吗?” 问题…或者,更好的是,“这会在哪里失败?建议改进?”问题

问题:
标题不应超过一行

测试文件:

You have a hold available for pickup as of 2012-01-13:
Title: Really Long Test Title Regarding Random Gibberish. Volume 1, A-B, United States
 and affiliated territories, United Nations, countries of the world
Author: Barrel Roll Morton
Copy: 3
#end-of-record
You have a hold available for pickup as of 2012-01-13:
Title: Short Catalogue of Random Gibberish. Volume 1, A-B, United States
Author: Skippy Credenza
Copy: 12
#end-of-record
预期产出:

You have a hold available for pickup as of 2012-01-13:
Title: Really Long Test Title Regarding Random Gibberish. Volume 1, A-B, United States
Author: Barrel Roll Morton
Copy: 3
#end-of-record
You have a hold available for pickup as of 2012-01-13:
Title: Short Catalogue of Random Gibberish. Volume 1, A-B, United States
Author: Skippy Credenza
Copy: 12
#end-of-record
我的解决方案:

sed -e '/^Title/{N;/\nAuthor:/!{s/\n.*$//}}' test-file.txt
我的逻辑是:上述建议的解决方案

  • 查找regex/^Title/
  • 抓住下一行
  • 如果下一行不匹配/^Author/
  • 然后搜索regex/\n*$/
  • 替换为nada

有没有更可靠的方法可以做到这一点呢?

看起来不错,但是如果你不能控制第一行文本的长度,你可以使用类似的方法进一步截断它

sed '/^Title/{N;/\nAuthor:/!{s/^\(....................\).*\n.*$/\1/;};}' test-file.txt
(你不需要-e,但也不痛)

我使用一个老式的sed,所以我需要
;};}额外位

根据要捕获的值的长度,调整匹配模式中的“.”数

较新的sed支持花括号范围,类似于,剪切,我无法确认

sed '/^Title/{N;/\nAuthor:/!{s/^\(.\{30,50\}\).*\n.*$/\1/;};}' test-file.txt
根据@JonathanLeffler在下面的评论进行编辑。固定范围表示法,将30,50更改为适合您的值


我希望这有帮助。

这可能对您有用:

sed '/^Title/,/^Author/{//!d}' file
如果要截断
标题
行,则

sed '/^Title/,/^Author/{//!d;s/^\(Title.\{25\}\).*/\1/}' file

这将
标题的长度减少到30个字符。

虽然不是您想要的(Poton的解决方案似乎是最好的),但下面将在单行中附加一个N行标题,而不是截断它

sed '/^Title:/{:a;N;/\nAuthor:/!s/\n//;ta;P;D}' test-file.txt
输出
如果您对
awk
没有问题,那么您可以这样做-

awk '/Title:/{print $0; getline; while ($0!~/Author:/) {getline}}1' file

您的版本提供了控制标题字符串长度的优势。然而,/*$/部分对我来说似乎有点“松散”。我想它考虑了空行,毕竟是安全的?当你做“N”时,你只会得到一行额外的输入,对吗?如果这真的很重要,我会查询我的数据源,看看数据中当前存在哪些角落案例,然后编写一个sed来解决这个问题。否则,可以在sed中循环执行“N”,直到找到作者,但它不再是一行;-)祝你好运。。还有一件事,我认为如果你有一行比字符匹配模式的长度短,那可能是个问题。如果您正在检查角盒的数据,请确保打印出最短的长度。在这一点上,我不确定我会做什么来解决这个问题。如果你需要帮助,请告诉我。祝你好运。即使是相当旧的
sed
版本也支持
\{lo,hi\}
范围符号。然而,“相当旧”并没有扩展到1978年的第7版UNIX。虽然不适用于这个特殊问题,但我仍然可以在下一批messes中使用它。我们将投票表决。谢谢所谓“不适用”,我只是指当前模板的约束要求一行少于70或80个字符。我计划更新模板--@Bubnoff谢谢。查看更新的答案。它现在可以处理任意长标题。这是一个有趣的破译。re:{//!d}-sed自动替换空白匹配斜杠中的最后一个匹配,对吗?那么//翻译成/^Author/?很好。如果标题少于30个字符怎么办?另外,在您的第一个示例中(顺便说一句),我看到它使用正则表达式范围…但是为什么不删除/^title/?@Bubnoff它只删除中间的行。替换命令必须先匹配,然后才能替换,如果
标题中没有30个字符
它将不起任何作用。您可以尝试
/^Author/{p=0};!p/^Title/{p=1}'文件
awk '/Title:/{print $0; getline; while ($0!~/Author:/) {getline}}1' file