2

Используя sed, как я могу заменить два шаблона в большем шаблоне на одной строке?

Учитывая одну строку текста, я хочу найти шаблон (назовем это внешним шаблоном), а затем в этом внешнем шаблоне заменить два внутренних шаблона.

Вот пример однострочного ввода текста:

Z:\source\private\main\developer\foo\setenv.sh(25):     export 'FONTCONFIG_PATH'="$WINE_SHARED_SUPPORT/X11/etc/fonts"

В приведенном выше примере внешним шаблоном является /^.*\([[:digit:]]+\):/ который должен быть равен Z:\source\private\main\developer\foo\setenv.sh(25): Два внутренних шаблона:/^[A-Za-z]:/ и /\\/ .

Другой способ сформулировать мой вопрос:

Используя sed, я знаю, как выполнять замены шаблона с помощью команды s , но как мне ограничить диапазон команды s чтобы она работала только на части входной строки до (25):

Конечный результат, который я пытаюсь получить - строка текста преобразуется в это:

/enlistments/source/private/main/developer/foo/setenv.sh(25):     export 'FONTCONFIG_PATH'="$WINE_SHARED_SUPPORT/X11/etc/fonts"

4 ответа4

1

Эта команда преобразует ваш входной пример в выходной пример:

sed 's|\\|/|g;s|^[^/]*|/enlistments|'

Если некоторые из ваших входных данных содержат обратную косую черту в части после /^.*([[:digit:]]+):/ части, то вам придется разделить и победить, чтобы предотвратить замену этих последних обратных косых черт.

sed 'h;s/^.*([[:digit:]]\+)://;x;s/^\(.*([[:digit:]]\+):\).*/\1/;s|\\|/|g;s|^[^/]*|/enlistments|;G;s/\n//'

Пояснение (шаги, отмеченные звездочкой ([*]) относятся к обеим командам):

  • h - скопировать строку для пробела
  • s/^.*([[:digit:]]\+):// - удалить первую часть строки из оригинала в шаблонном пространстве
  • x - поменять местами шаблон и удерживать пространство
  • s/^\(.*([[:digit:]]\+):\).*/\1/ - сохранить первую часть строки из копии (отменить последнюю часть)
  • s|\\|/|g - [ * ] изменить все обратные косые черты на косые черты (в версии «разделяй и властвуй» затрагивается только часть в шаблонном пространстве - первая часть строки)
  • s|^[^/]*|/enlistments| - [ * ] измените все, что появляется перед первой косой чертой, в "/enlistments" - при необходимости это можно сделать более избирательным
  • G - добавить новую строку и содержимое области удержания в конец пространства шаблона
  • s/\n// - убрать внутреннюю строку
0

Это может работать для вас (GNU sed):

sed 's/([0-9]\+):/&\n/;h;s/\n.*//;y/\\/\//;s/[^/]*/\/enlistments/;G;s/\n.*\n//' file
0

Есть два факта, которые, я думаю, вы найдете полезными:

  1. По умолчанию sed заменяет только первое вхождение строки в строке. Итак, с учетом следующей строки:

    foo foo
    

    Команда sed s/foo/bar/ приведет к:

    bar foo
    
  2. Вы можете ограничить команду sed линиями, соответствующими определенному шаблону. Если вы хотите выполнить вышеуказанную замену только для строк, содержащих строку "xyz", вы должны использовать команду, подобную этой:

    sed '/xyz/ s/foo/bar/'
    

Я думаю, что это должно помочь вам сделать то, что вы хотите.

0

Вы могли бы попробовать

sed -r 's/^[A-Z]:\\|\\/\//g' | sed 's/^/\/enlistments/'

Теперь это, конечно, требует, чтобы после (25) в обратной части не было обратной косой черты: чтобы работать. Но, как я подозреваю, этого никогда не произойдет из-за структуры пути Unix, этого никогда не произойдет.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .