我必须用文本替换35-79和235-249中的所有数字,让我们说“你好世界”。
几分钟后,我想出了一个表达式:
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被检测为有效输入,这不是我想要的。这些数字前面跟着空格或随机字母数字字符,因此使用单词边界将不是一个选项。我成功地使用了负回顾和负展望来解决这个问题,得到了以下结果:
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中解决这个问题吗?
发布于 2020-10-15 12:38:29
用perl
$ 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
检查的语法,在其他实现中将有所不同)
$ 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
字符,以避免循环运行foreverta
分支来标记a
,只要替换succeedss/\n//g
删除额外的换行符。
https://stackoverflow.com/questions/64371281
复制相似问题