regex - 使用 sed 将一个子字符串替换为另一个子字符串

标签 regex sed

看看以下路径:

/iil/some/path/data/file1
iil/some/path/log/file2
/iil/some/path/BinDir1/file3
iil/some/path/BinDir2/file4

我想使用 sed 来转换以 /iilill 开头的每个子字符串,直到它满足其中一个以下单词:data,log,BinDir*。所以输出将是:

[PATH]/data/file1
[PATH]/log/file2
[PATH]/BinDir1//file3
[PATH]/BinDir2/file4

我尝试过的:

echo "/iil/path/data/file1" | /usr/bin/sed "s/\(\/|)iil.*\(data\|log\|BinDir*\)/[PATH]\/g"

但它没有按预期工作。有什么建议吗?

最佳答案

您原来的 sed 命令存在一些问题:

  • | 交替运算符在第一组中不会转义,并且会作为文字管道符号进行匹配,因为该模式被解析为 BRE POSIX 正则表达式
  • 第一组已损坏,因为尾随 ) 未转义
  • 未使用数字匹配模式,您只是量化了 rr* 匹配 0+ r 个字母
  • RHS 中没有占位符,并且捕获到第 2 组的单词将被删除(尽管您通过转义最后一个 / 分隔符破坏了该命令)。

你可以修复你自己的命令,例如

echo "/iil/path/data/file1" | \
   sed 's/\(\/\|\)iil.*\(data\|log\|BinDir[0-9]\)/[PATH]\2/'

参见the demo

但是,您很可能希望立即匹配直到第一个 datalogBinDir遵循/。因此,我建议使用 Perl 解决方案,因为 Perl 支持非贪婪量词:

perl -pe 's,^/?iil/(?:.*?/)?(data|log|BinDir\d+),/$1,'

参见this demo .

详细信息

  • ^ - 字符串/行的开头
  • /? - 可选的 /
  • iil/ - iil/ 子字符串
  • (?:.*?/)? - 可选的非捕获组,匹配除换行符之外的任意 0 个以上字符的 1 次或 0 次出现,直到第一次出现为止尽可能少后续子模式
  • (data|log|BinDir\d+) - 第 1 组:data、或 logBinDir后跟 1+ 位数字。

替换为 /$1、斜线和第 1 组的内容。

关于regex - 使用 sed 将一个子字符串替换为另一个子字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53480823/

相关文章:

linux - 使用 sed 脚本每隔一行将当前行的一部分与下一行的一部分组合起来

php - 用于验证 facebook 页面 url 的正则表达式

awk - 用 n 个零填充列并修剪多余的值

Linux - 根据模式将文件中的长行拆分为多行

c - 将字符串解析为多个变量

sed - 使用sed查找长度超过120个字符的行

bash - 通过一行命令在 Ubuntu 中编辑 conf 文件

php - 在英语(和非英语字母)上用 preg_split 拆分字符串

javascript - gulp uncss 意外删除了一些 "ignored"类

Python最大执行超时或加速正则表达式