2 つの正規表現パターン間の文字列の削除

2 つの正規表現パターン間の文字列の削除

次の内容を含むファイルがあります。

..\..\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を含むあいまいさを避けるために、置換s()コマンドの区切り文字として使用されます。sed\

  • (.*\\src)最初から一致を開始しsrc、一致をキャプチャグループ1に配置します。

  • (\\[^\]+\\[^\]+$)2つの部分を最後まで\一致させ、キャプチャグループ2に配置します。.*先行することは、第1のキャプチャグループと第2のキャプチャグループとの間の全ての項目と一致する。

  • 交換では、2つのキャプチャされたグループを使用しました。

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

代替ソリューション:

GNUgreppaste

grep2つのパターンを抽出する.*\\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 }'

関連情報