刪除兩個正規表示式模式之間的字串

刪除兩個正規表示式模式之間的字串

我有一個包含以下內容的文件

..\..\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 來實現這一目標?

我無法編寫正則表達式來同時捕獲兩個組。

  1. 初始群組 (....\src) - 這在所有行中都是相同的
  2. 變數組 (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

替代解決方案:

與 GNUgreppaste

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 }'

相關內容