首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >负前瞻和负查找的Sed替换

负前瞻和负查找的Sed替换
EN

Stack Overflow用户
提问于 2020-10-15 12:09:20
回答 1查看 296关注 0票数 2

我必须用文本替换35-79235-249中的所有数字,让我们说“你好世界”。

几分钟后,我想出了一个表达式:

代码语言:javascript
运行
复制
sed -r "s/((3[5-9]|[4-7][0-9])|(23[5-9]|24[0-9]))/[\1 hello world]/g" file1.txt > file2.txt

我遇到的问题是,它也将较大数字的一部分识别为有效数字。例如,在数字256中,56被检测为有效输入,这不是我想要的。这些数字前面跟着空格或随机字母数字字符,因此使用单词边界将不是一个选项。我成功地使用了负回顾和负展望来解决这个问题,得到了以下结果:

代码语言:javascript
运行
复制
sed -r "s/(((?<![0-9])3[5-9](?![0-9])|(?<![0-9])[4-7][0-9](?![0-9]))|(23[5-9]|24[0-9]))/[\1 hello world]/g" file1.txt > file2.txt

不幸的是,sed没有识别后视镜和前瞻。我知道Perl会这么做,但我不得不只使用sed。知道如何在sed中解决这个问题吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-15 12:38:29

perl

代码语言:javascript
运行
复制
$ echo '40-840-236;59a' | perl -pe 's/(?<!\d)(23[5-9]|24\d|3[5-9]|[4-7]\d)(?!\d)/[$1 hello world]/g'
[40 hello world]-840-[236 hello world];[59 hello world]a

使用sed (使用GNU sed检查的语法,在其他实现中将有所不同)

代码语言:javascript
运行
复制
$ echo '40-840-236;59a' | sed -E ':a s/(^|[^0-9])(3[5-9]|[4-7][0-9]|23[5-9]|24[0-9])([^0-9\n]|$)/\1[\2\n hello world]\3/; ta; s/\n//g'
[40 hello world]-840-[236 hello world];[59 hello world]a

  • :a label a
  • (^|[^0-9])匹配行的开始或非数字的character
  • (3[5-9]|[4-7][0-9]|23[5-9]|24[0-9])有效数字是matched
  • ([^0-9\n]|$)匹配非数字、非换行符或line
  • \1[\2\n hello world]\3的所有捕获组的结束,需要输出格式,加上一个额外的newline字符,以避免循环运行forever
  • ta分支来标记a,只要替换succeeds
  • s/\n//g删除额外的换行符

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64371281

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档