
我有一個包含以下內容的文件
..\..\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-ly:
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 }'