Удалить строку между двумя шаблонами регулярных выражений

Удалить строку между двумя шаблонами регулярных выражений

У меня есть файл со следующим содержимым

..\..\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

В BSD sedили последних версиях GNU sed(для более старых версий замените -Eна -r):

sed -E 's#(.*\\src).*(\\[^\]+\\[^\]+$)#\1\2#' file.txt
  • #используется как разделитель для sкоманды подстановки ( ) sed, чтобы избежать неоднозначности, связанной с \s во входных данных

  • (.*\\src)совпадения с самого srcначала и помещаем совпадение в захваченную группу 1

  • (\\[^\]+\\[^\]+$)соответствует части, имеющей два \s до конца, и помещается в захваченную группу 2, .*предшествующая этому соответствует всему, что находится между первой и второй захваченными группами

  • В замене мы использовали две захваченные группы

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

Альтернативные решения:

С GNU grepи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 }'

Связанный контент