我有一个包含以下内容的文件
..\..\src\modules\core\abc\abc.cpp
..\..\src\modules\core\something\xyz\xyz.cpp
..\..\src\other_modules\new_core\something\pqr\pqr.cpp
..\..\src\other_modules\new_core\something\pqr\abc.cpp
我期待的结果是
..\..\src\abc\abc.cpp
..\..\src\xyz\xyz.cpp
..\..\src\pqr\pqr.cpp
..\..\src\pqr\abc.cpp
我怎样才能使用 sed 实现这一目标?
我无法编写正则表达式来同时捕获两个组。
- 初始组 (....\src) - 这在所有行中都是相同的
- 变量组 (abc\abc.cpp) 或 (xyz\xyz.cpp) 或 (pqr\pqr.cpp) 或 (pqr\abc.cpp)
答案1
使用 BSDsed
或最新版本的 GNU sed
(对于旧版本,替换-E
为-r
):
sed -E 's#(.*\\src).*(\\[^\]+\\[^\]+$)#\1\2#' file.txt
#
用作 的替换 (s
) 命令的分隔符sed
,以避免\
输入中涉及 s的歧义(.*\\src)
从头开始匹配src
,并将匹配放入捕获组 1(\\[^\]+\\[^\]+$)
匹配直到结束为止有两个 s 的部分\
,并放入捕获组 2,.*
前面的 this 匹配第一个和第二个捕获组之间的所有内容在替换中,我们使用了两个捕获的组
POSIX 风格:
sed 's#\(.*\\src\).*\(\\[^\]\+\\[^\]\+$\)#\1\2#' file.txt
例子:
% cat file.txt
..\..\src\modules\core\abc\abc.cpp
..\..\src\modules\core\something\xyz\xyz.cpp
..\..\src\other_modules\new_core\something\pqr\pqr.cpp
..\..\src\other_modules\new_core\something\pqr\abc.cpp
% sed -E 's#(.*\\src).*(\\[^\]+\\[^\]+$)#\1\2#' file.txt
..\..\src\abc\abc.cpp
..\..\src\xyz\xyz.cpp
..\..\src\pqr\pqr.cpp
..\..\src\pqr\abc.cpp
答案2
替代解决方案:
与 GNUgrep
和paste
grep
提取两个模式.*\\src
或(\\[^\]+){2}$
并将它们打印在单独的行上。然后使用组合输出paste
$ grep -oE '.*\\src|(\\[^\]+){2}$' ip.txt | paste -d '' - -
..\..\src\abc\abc.cpp
..\..\src\xyz\xyz.cpp
..\..\src\pqr\pqr.cpp
..\..\src\pqr\abc.cpp
和perl
$ perl -pe 's/.*\\src\K.*(?=(\\[^\\]+){2}$)//' ip.txt
..\..\src\abc\abc.cpp
..\..\src\xyz\xyz.cpp
..\..\src\pqr\pqr.cpp
..\..\src\pqr\abc.cpp
这里,模式之间的文本通过使用积极的环视被.*\\src
删除(\\[^\\]+){2}$
答案3
创建一个包含数据的文件
-rwxr-xr-x. 1 sasi webApp 190 Oct 4 13:42 file.txt
执行以下命令
[sasi@localhost temp]$ sed -E 's#(.*\\src).*(\\[^\]+\\[^\]+$)#\1\2#' file.txt
..\..\src\abc\abc.cpp
..\..\src\xyz\xyz.cpp
..\..\src\pqr\pqr.cpp
..\..\src\pqr\abc.cpp
[sasi@localhost temp]$
[sasi@localhost temp]$
[sasi@localhost temp]$
答案4
为什么用正则表达式来攻击它?路径修改不需要正则表达式;操作系统内核不使用正则表达式来跟踪路径。
使用 Awk,我们只需使用反斜杠作为分隔符,组件就成为字段:
awk 'BEGIN { FS = OFS = "\\" } { print $1, $2, $3, $(NF-1), $NF }'