sed: заданное имя файла с абсолютным путем, замена только для имени файла. Работает только когда шаблон находится в начале имени файла - PullRequest
1 голос
/ 30 мая 2019

Я работаю над шаблоном замены sed, который берет имя файла с абсолютным путем и затем печатает неизмененный ввод, а также измененный ввод (который должен применяться только к имени файла, а не к пути).Некоторый путь гарантированно определен явно, поэтому ему никогда не будет дано что-то вроде «test.c», в этом случае это будет «./test.c».

У меня есть работающее регулярное выражение, но только когда заменяемая часть находится в начале имени файла.Я хотел бы, чтобы он работал с любой частью имени файла.

Чтобы уточнить, вот краткое изложение текущего поведения.

INPUT           PATTERN              CURRENT OUTPUT       DESIRED BEHAVIOR?

./test.c        p;s;\(.*/\)t;\1###;  ./test.c             Yes
                                     ./###est.c

testdir/test.c  p;s;\(.*/\)tes;\1#;  testdir/test.c       Yes
                                     testdir/#t.c

./test.c        p;s;\(.*/\)est;\1#;  ./test.c             NO
                                     ./test.c             Should be ./t#.c

Как вы можете видеть, это мой шаблон:

p;s;\(.*/\)SubstringToFind;\1SubstringToInsert;

Вот моя логика для этого:

p, чтобы напечатать неизмененную строку

s для замены (да, мы все это знаем)

Захватить путь: любое количество символов плюс конечный "/"

SubstringToFind: искать шаблон где-нибудь в имени файла.

\1: восстановить неизмененноепуть

SubstringToInsert: вставить измененное имя файла

Я уверен, что это просто вызывает одно крошечное добавление, такое как еще одно ". *", которое я пытался добавить сразу после захватаскобки, но это просто заменяет указанный шаблон вместе со всеми символами имени файла перед ним.Я уверен, что решение смотрит мне в лицо, но я не вижу его.Любая помощь от кого-то более опытного в регулярных выражениях, чем я?Спасибо!

1 Ответ

1 голос
/ 30 мая 2019

Вы действительно были очень близки. Ваш шаблон для последнего случая ищет est сразу после косой черты, указанной в захвате, но est не сразу после косой черты.

Вам нужно:

$ echo ./test.c | sed -e 'p;s;\(.*/[^/]*\)est;\1#;'
./test.c
./t#.c
$

Я использовал класс отрицанных символов, чтобы избежать совпадения, которое может дать .*, но вы также можете использовать это (и я не уверен, что на самом деле есть существенное преимущество для класса отрицанных символов). Немного более строгий тест:

$ printf '%s\n' ./test.c ./southwest.c ./west-by-southwest.c south/west/southwestern.c |
> sed -e 'p;s;\(.*/[^/]*\)est;\1#;'
./test.c
./t#.c
./southwest.c
./southw#.c
./west-by-southwest.c
./west-by-southw#.c
south/west/southwestern.c
south/west/southw#ern.c
$
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...