Извлечь путь из текстового файла с помощью команды sed

Вопрос или проблема

Содержимое one.txt приведено ниже.

Привет, это первая строка в файле one.txt
cooler:строка по умолчанию cooler `/var/log/cooler_x86_64_someos8.4/config.cf'
всё хорошо, супер!
всё в порядке
Привет, это последняя строка в файле one.txt

Ожидаемый вывод

/var/log/cooler_x86_64_ubantu.8.24/config.cf

Мне нужно как ниже

cat one.txt | grep cooler | sed somergexp

Разъяснение:

Да, первая – обратная кавычка, а последняя – одинарная кавычка

`/var/log/cooler_x86_64_someos8.4/config.cf'

Я смог это сделать, используя два sed как ниже

sed 's:^.*\(`.*\)'\''.*$:\1:'| sed 's/`//'

но нужно сделать с помощью одного вызова sed.

Я смог решить проблему с sed 's:[^/]*\(.*\)'\''.*$:\1:'

sed -n -r '/^cooler/s|.*['\''`"]([^'\''"`]+).*|\1|gp' one.txt

-n молчание
/^cooler/ шаблон
gp – вывод результата
.*['\''`"] – группа символов перед кавычками (‘`”)
([^'\''"`]+) – группа символов после кавычки, кроме следующих кавычек (‘`”)

Давайте начнем с выбора строки, которая нас интересует. Эта строка начинается со строки cooler::

$ sed -e '/^cooler:/!d' file
cooler:строка по умолчанию `/var/log/cooler_x86_64_someos8.4/config.cf'

Выражение /^cooler:/!d удалит все строки из входных данных, которые не соответствуют /^cooler:/.

Затем мы извлекаем то, что между обратной кавычкой и кавычкой:

$ sed -e '/^cooler:/!d' -e "s/.*\`\([^']*\)'.*/\1/" file
/var/log/cooler_x86_64_someos8.4/config.cf

Выражение s/.*\`\([^']*\)'.*/\1/ заменяет всю строку на строку внутри `...'. Обратная кавычка должна быть экранирована, так как это выражение находится в двойных кавычках (в противном случае она бы начала подстановку команды в оболочке).

Вы также можете выполнить извлечение пути в два этапа: удалить все до и включая обратную кавычку, а затем удалить все после и включая одинарную кавычку. Это может даже выглядеть немного аккуратнее:

$ sed -e '/^cooler:/!d' -e 's/.*`//' -e "s/'.*//" file
/var/log/cooler_x86_64_someos8.4/config.cf

Еще несколько вариантов регулярных выражений

  1. Используя sed

    sed -n '/^cooler:/s/^.*`\(.*\)'"'"'/\1/p'
    

    Это можно объяснить следующим образом

    • -n не выводить ничего, если нет совпадения
    • ^cooler: искать cooler: в начале строки
    • s/old/new/p заменить old на new и напечатать результат, если замена прошла успешно
    • ^.*`\(.*\)'"'"' соответствует всему до обратной кавычки, затем захватывает все внутри скобок (), затем захватывает одинарную кавычку до конца строки. '"'"' – это оболочка: первая ' завершает исходную строку в одинарных кавычках, "'" экранирует одинарную кавычку, а финальная ' перезапускает строку в одинарных кавычках
    • \1 в части замены ссылается на захваченную строку из совпадения по шаблону
  2. Используя GNU grep

    grep -oP '^cooler:.*`\K'"[^']*"
    

    Это можно объяснить почти так же, как и раньше

    • -oP только печатать совпадение и использовать регулярные выражения perl (PCRE) для разбора
    • \K граница: все, что перед ней, совпадает, но отбрасывается; все, что после, включается в результат
    • [^']* соответствует всему, кроме одинарной кавычки
$ sed -ne '
   /^cooler:/y/`'\''/\n\n/
   s/.*\n\(.*\)\n.*/\1/p
' one.txt

Это posix sed, и мы заменяем кавычку и обратную кавычку на новые строки. Затем путь находится
между двумя новыми строками.

Чтобы извлечь текст между внешними совпадающими парами `...', вы можете сделать:

pcregrep -o2 "(\`((?:(?1)|[^\`']++)*+)')"

Используя рекурсивное сопоставление в стиле perl.

Или:

perl -lne "print for /(\`((?:(?1)|[^\`']++)*+)')/g"

Или чтобы ограничить только теми, которые начинаются с /:

perl -lne "for (/(\`((?:(?1)|[^\`']++)*+)')/g) {print if m{^/}}"

Ответ или решение

Для выполнения задачи извлечения пути из текстового файла с именем one.txt, содержащего определенный формат данных, мы можем использовать команду sed в Linux. Ваша цель — вытащить строку, находящуюся между обратной кавычкой ` и одинарной кавычкой ', и это можно сделать, используя правильные регулярные выражения.

Пошаговое руководство

  1. Фильтрация строки: Сначала нужно отобрать строку, содержащую подстроку "cooler:". Для этого мы используем команду sed с фильтром, чтобы оставить только нужные строки.

  2. Извлечение текста: После того как вы фильтровали строки, нужно использовать sed для извлечения текста непосредственно между ` и '.

Основная команда sed

Для одной команды всё можно свести к следующему:

sed -n -e '/cooler:/s/.*`\(.*\)'\''/\1/p' one.txt

Объяснение команды:

  • -n: Этот параметр отключает автоматический вывод, позволяя печатать только то, что явно указано с помощью команды p.
  • /cooler:/: Это регулярное выражение находит строки, содержащие "cooler:".
  • s/.*(.*)’\”/\1/p`: Это выражение следующее:
    • .* до обратной кавычки находит всё до неё.
    • \(.*\) захватывает всё после обратной кавычки и до одинарной кавычки.
    • '\'' указывает на конец искомой строке, где кавычка экранирована.
    • \1 в замене возвращает захваченное значение (путь).
    • p — печатает полученное значение.

Пример выполнения

Если файл one.txt содержит следующую строку:

cooler:some default cooler string `/var/log/cooler_x86_64_someos8.4/config.cf'

Запустив описанную выше команду, вы получите:

/var/log/cooler_x86_64_someos8.4/config.cf

Итог

Таким образом, с помощью команды sed мы эффективно извлекаем путь из строки, используя одну вызов команды вместо нескольких. Использование регулярных выражений дает возможность точно нацеливаться на данные, которые нам нужны, минимизируя при этом лишние операции.

Это решение упрощает процесс работы с текстовыми файлами в системах Unix/Linux и является отличным примером мощности утилиты sed в обработки текста.

Оцените материал
Добавить комментарий

Капча загружается...