
У меня есть файл со следующим содержимым
..\..\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
В 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 }'