извлечь значение между двумя шаблонами поиска на одной строке

У меня есть следующее в файле Output.dat. Мне нужно извлечь значение между dn: uid = и , ou =

dn: uid=user1,ou=Active,ou=Member,dc=domain,dc=org dn: uid=user2@abc.com,ou=Active,ou=Member,dc=domain,dc=org dn: uid=usertest,ou=Active,ou=Member,dc=domain,dc=org dn: uid=abc1,ou=Active,ou=Member,dc=domain,dc=org 

Я попытался использовать `sed -e '/ dn: uid = /, /, ou = / p' output.dat, но он возвращает полную строку вместо значения.

при попытке использовать sed -e '/dn: uid=/,/,ou=/\1/p' output.dat затем получил следующую ошибку:

  sed: -e expression #1, char 18: unknown command: `\' 

  • Разделить текстовый файл на строки с фиксированным числом слов
  • Использование sed для поиска и замены сложной строки (желательно с регулярным выражением)
  • Как извлечь данные из файла и построить имя файла из одного из значений
  • Скопируйте текстовые строки из файла и добавьте их в один и тот же файл с префиксом средней линии или удалите префикс средней строки
  • Удалить пробелы после определенного символа
  • sed - удалить unmatched "}", ")" или "]" (только для рассматриваемой строки)
  • разделить линию на основе пробела и удалить вторую часть
  • Поиск текстового файла по столбцу
  • 4 Solutions collect form web for “извлечь значение между двумя шаблонами поиска на одной строке”

    Если у вас есть версия GNU grep с поддержкой PCRE ( -P ), то, предполагая, что вы имеете в виду первое появление ,ou

     grep -oP '(?<=dn: uid=).+?(?=,ou=)' file 

    Если вы хотите совпадение со вторым ,ou вы можете удалить не жадных ? модификатор

     grep -oP '(?<=dn: uid=).+(?=,ou=)' file 

    Выражения в круглых скобках – это утверждения с нулевой длиной (aka lookarounds ), что означает, что они являются частью соответствия, но не возвращаются как часть результата. Вы можете сделать то же самое изначально в perl, например

     perl -ne 'print "$1\n" if /(?<=dn: uid=)(.+?)(?=,ou=)/' file 

    В sed можно сделать что-то подобное , используя регулярную (не нулевую) группировку, например (для GNU sed – для других сортов может потребоваться дополнительное экранирование)

     sed -rn 's/(.*dn: uid=)([^,]+)(,ou=.*)/\2/p' file 

    или упрощение

     sed -rn 's/.*dn: uid=([^,]+),ou=.*/\1/p' file 

    Обратите внимание, что [^,] здесь немного взломан, так как у sed нет истинного варианта неживого соответствия.

    Последующая мысль : хотя это не совсем то, что вы просили, похоже, что вы действительно хотите сделать, это прочитать разделенные запятыми name=value пары name=value из файла, а затем еще разделить значение первого поля от его имени. Вы можете добиться этого во многих отношениях – в том числе

     awk -F, '{sub(".*=","",$1); print $1}' file 

    или решение с чистым башем, такое как

     while IFS=, read -rabcd; do printf '%s\n' "${a#*=}"; done < file 

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

     $ awk -F= '{ split($2,arr,","); print arr[1] }' test.txt user1 user2@abc.com usertest abc1 

    С sed :

     sed 's/[^=]*=\([^,]\+\),.*/\1/' file 

    Это предполагает, что uid= будет иметь первое вхождение = на линии и предполагает, что вы хотите остановиться на первом ,ou= экземпляре в строке.

    объяснение

    Это ищет любое число non = characters ( [^=]* ), за которым следует = затем сопоставляет и сохраняет как можно больше не запятых ( \([^,]\+\) ), за которыми следует запятая и остаток строки ( ,.* ). Это означает, что он заменит все до и включая первое = и после первой запятой с любыми не запятыми символами, которые он найдет после первого = на линии.

    Несколько вариантов, в порядке длины:

    1. GNU grep с помощью PCRE

       grep -oP 'uid=\K[^,]+' file 

      \K отбрасывает все, что соответствует этой точке, что в сочетании с ключом -o вызовет grep для печати только самого длинного участка non , символов, которые появляются после uid= .

    2. awk

       awk -F'[=,]' '{print $2}' file 

      -F'[=,] устанавливает разделитель полей равным либо = или , поэтому второе поле является именем пользователя.

    3. sed

       sed -r 's/.{8}([^,]*).*/\1/' file 

      Это будет соответствовать первым 7 символам ( .{7} ) = , захватить самый длинный участок non , как \1 и заменить всю строку на \1 .

    4. perl

       perl -pe 's/.+?=([^,]+).*/$1/' file 

      Параметр -pe означает «распечатать каждую строку после применения сценария, заданного -e». s/// – это оператор подстановки, и регулярное выражение ищет 1-е ( .+? Оно делает его совпадающим с кратчайшей возможной строкой) = а затем захватывает самый длинный отрезок символа non , после этого. s/// заменяет то, что было сопоставлено с тем, что было захвачено (что было в круглых скобках).

    5. cut

       cut -d'=' -f 2 file | cut -d ',' -f 1 

      Параметр -d устанавливает разделитель равным = so, тогда поле 2nd ( -f 2 ) является username,ou . Второй cut использует в качестве разделителя и печатает только имя пользователя.

    Linux и Unix - лучшая ОС в мире.