Intereting Posts
Источник аудиосигнала Bluetooth A2DP для воспроизведения звука с телефона на linux с помощью bluez 5.45 Как отсортировать результаты из команды ls по дате изменения (сначала в каталогах)? Заставьте systemd-timesyncd не слушать IPv6 Установка mlocate на Mac OS 10.7 труба не записывает в файл Ограничивает ли POSIX количество каталогов в корневом каталоге os? Как перечислить драйверы принтеров без учетных данных с Samba? Как скопировать текст в xterm Как обрабатывать действие Eject от Nautilus в файловой системе FUSE? В чем разница между .ini и .conf? Каков наилучший способ скопировать файлы из файловой системы ext3 в NTFS и сохранить права собственности и разрешения? Как найти различия между macOS и linux wifi-драйверами на Mac-оборудовании? Как я могу запустить byobu из xterm при запуске? Отключить выключение экрана в KDE во время просмотра iPlayer Как определить, использует ли плата Linux аппаратное FPU или нет?

Sed для удаления между разделителями, но сохранить первый разделитель

Мне нужно удалить все между вторым = в строке и первой / в строке, но сохранить = на месте. Я пробовал много-много вещей, последние из которых

 sed -i 's/=[^/]*// 

Начал писать об ожиданиях и ожиданиях только для того, чтобы узнать, что sed их не поддерживает! Это должно сделать трюк:

sed -i 's!\(=[^=]*=\)[^/]*/!\1!'

  • Поскольку мы используем / character в regexp, мы меняем разделитель команды s на !
  • \(=[^=]*=\) – группа захвата, которая соответствует одному символу, за которым следуют ноль или несколько других символов, за которым следует символ другого = . Эта часть необходима, чтобы удостовериться, что есть две = символы перед подстрокой, которую вы хотите удалить, поскольку вы сказали, что вам нужно
  • [^/]*/ соответствует тому, что находится между разделителями и вторым разделителем
  • \1 заменяет всю согласованную строку тем, что соответствовало группе захвата \(=[^=]*=\)

Основываясь только на текстовом описании, без ввода ввода / вывода, я придумал следующее:

 $ echo "foo=bar=baz/quux" | sed 's/\(.*=.*\)=.*\/\(.*\)/\1=\2/' foo=bar=quux 

Насколько близко это происходит к тому, что вы хотите?

Вот одно решение с perl

 $ echo 'foo=bar=baz/quux' | perl -pe 's|^([^=]+=){2}\K[^=/]+/||' foo=bar=quux $ echo 'abc=foo=bar=baz/quux' | perl -pe 's|^([^=]+=){2}\K[^=/]+/||' abc=foo=bar=baz/quux 

Как видно из приведенных выше примеров, это ограничивает удаление текста только с 2-го = до /

  • ^([^=]+=){2}\K от начала строки найти 2 последовательности не = текст, за которыми следует = . \K означает положительный lookbehind, а не часть строки замены
  • [^=/]+/ означает один или несколько символов не =/ заканчивающиеся на /
    • Если такой текст найден, он удаляется

Такое же решение с sed

 $ echo 'foo=bar=baz/quux' | sed -E 's|^(([^=]+=){2})[^=/]+/|\1|' foo=bar=quux $ echo 'abc=foo=bar=baz/quux' | sed -E 's|^(([^=]+=){2})[^=/]+/|\1|' abc=foo=bar=baz/quux 

Он не поддерживает конструкции lookahead / lookbehind, поэтому группа захвата, используемая и обратная, при замене