【问题标题】:Sed Regex OSX find Roman numerals and replace with empty string. Error "unterminated substitute pattern"Sed Regex OSX 查找罗马数字并用空字符串替换。错误“未终止的替代模式”
【发布时间】:2018-03-22 14:22:32
【问题描述】:

这可能是 Sed 和 shell 脚本语法问题以及 Regex。 (编辑:可能是 I/O 问题,因为在 bash shell 中读取文件时正则表达式起作用,但实际的 .txt 文件没有按需要更改)

尝试为一些自然语言处理工作准备一个.txt 文件。想要删除包含莎士比亚十四行诗的纯文本文件中的一些罗马数字,每个十四行诗都以罗马数字开头,例如IX.XVIII.,代表单个十四行诗的标题,包括十进制字符。

输入文本示例:

二十五。

让那些喜欢自己的明星

以公共荣誉和自豪的头衔夸耀,

期望的输出:

让那些喜欢自己的明星

以公共荣誉和自豪的头衔夸耀,

按照this question 中的示例,我在终端 bash shell 中尝试了以下所有命令:

$ sed -i 's/[IVXLC]{1,}[.]//g' sonnets.txt

$ sed -i 's/[IVXLC]{1,}[.]/^$/g' sonnets.txt

$ sed -i 's/[IVXLC]{1,}[.]/()/g' sonnets.txt

$ sed -i 's/[IVXLC]{1,}[.]/[]/g' sonnets.txt

这个想法是用空字符串替换任何匹配项。由于这不起作用,我尝试用空格字符替换匹配:

$ sed -i 's/[IVXLC]{1,}[.]/^ $/g' sonnets.txt

运气不好。上面的所有命令都返回相同的错误:

sed: 1: "sonnets.txt": unterminated substitute pattern

我在https://regexr.com/ 的“查找”字段中测试了正则表达式,它似乎是正确的。目标文件就在工作目录中。知道出了什么问题吗?我应该在 Sed 命令的“替换”字段中使用哪些字符?我应该修改正则表达式和/或 Sed 命令吗?

【问题讨论】:

  • 你能粘贴示例文本吗?输入是什么,你喜欢输出的样子。 ?
  • 我认为{} 需要转义。 \{\}。方括号可能还需要转义不确定。
  • {}[]regexr.com 上测试时似乎不是问题
  • 您是否还需要在 OS X 上为-i 提供文件扩展名?不正确的转义不会导致该错误消息,但我无法测试。
  • 请注意,sed 在 Mac 上的版本是 BSD 版本,而不是 GNU 版本。这些行为在很多方面都不同。

标签: regex bash macos shell sed


【解决方案1】:

大括号需要转义。

$ sed  's/[IVXLC]\{1,\}[.]//g'  sonnets.txt


Let those who are in favour with their stars

Of public honour and proud titles boast,

【讨论】:

    【解决方案2】:

    正如@Jonathan Leffler 在 cmets 中提到的,我的 Mac 使用的是 BSD sed,这就是该命令不起作用的原因。

    所以我通过 Homebrew 安装了 GNU sed

    brew install gnu-sed

    然后使用命令:

    gsed -i 's/[IVXLC]\{1,\}[.]//g' sonnets.txt

    输入 gsed 会调用 GNU sed,它可以正常工作。它改变了.txt 文件的内容。

    在这种配置中,正如@Hakan Baba 所提到的,正则表达式确实需要转义大括号:

    \{\}

    【讨论】:

    • 您实际上可以在此处不使用范围/限制量词,请参阅我的答案。
    【解决方案3】:

    问题似乎在于您的 BSD sed 版本不支持的范围(或 limiting )量词 {m,n}。请注意,您可以使用 [IVXLC][IVXLC]* 重写 {1,} 量词(一个罗马“数字”后跟 0+ 罗马数字):

    sed -i 's/[IVXLC][IVXLC]*[.]//g' sonnets.txt
              ^^^^^^^^^^^^^^^
    

    此外,如果您需要确保只匹配行首的罗马数字,请在模式的开头附加 ^(这意味着您也可以在末尾省略 g 修饰符正则表达式)。要将它们作为整个单词进行匹配,请在模式的开头添加 [[:<:]] 前导单词边界。

    【讨论】:

    • [IVXLC][IVXLC]* 的有趣想法!对于我正在处理的这份特殊文件,它包含超过 100 个罗马数字,表示莎士比亚写的所有十四行诗。标记整个文本输入的开头和结尾的 ^$ 字符可能不适用。
    • 但是,[[:<:]] 初始单词边界可能很有趣。
    猜你喜欢
    • 1970-01-01
    • 2014-09-05
    • 1970-01-01
    • 1970-01-01
    • 2013-03-23
    • 2020-12-15
    • 2020-09-12
    • 2019-02-15
    相关资源
    最近更新 更多