Извлечь все подстроки, которые соответствуют шаблону в Unix - PullRequest
0 голосов
/ 24 мая 2018

У меня есть строка в текстовом файле, как показано ниже.

<sample:Recipients><sample:user name="11111111" guid="8fa4fbaabf904a16ad65449bd7adcba1"/><sample:user name="22222222" guid="f74ebd3310834601a2c22a5dde33c02a"/><sample:user name="33333333" guid="5fcd2e7775cb42ecbed5ac5dd85e1ca6"/></sample:Recipients>

Строка является непрерывной и не отформатирована как правильная xml

Мне нужно извлечь все значения из тегов

Я использовал приведенный ниже скрипт

grep -o "<sample:Recipients>.*</sample:Recipients>" "sample.txt"|sed -n 's/.*\([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]\).*/\1/p'

Но я получаю только последнее значение 33333333.Как я могу извлечь значения из всех пользовательских тегов?

Ответы [ 3 ]

0 голосов
/ 24 мая 2018

Следующий сингл awk может вам помочь.

awk '
{
  while(match($0,/sample:user name=\"[^"]*[0-9]+/)){
    print substr($0,RSTART+18,RLENGTH-18);
    $0=substr($0,RSTART+RLENGTH+1)}
}'  Input_file
0 голосов
/ 24 мая 2018

Вы можете попробовать этот awk script ":

awk -v RS='<[a-z:]+|/>' -v FS='[a-z]+=' '{gsub("[\" ]",""); print $2,$3}'

Разделитель записей RS настроен на получение всего между <...\>. Разделитель полей настроен на захват левой части знака =.

Команда gsub избавляет от двойных кавычек и лишних пробелов.

В операторе print отображаются имя и guid. Если вам не нужен guid, удалите ,$3 в операторе print.

0 голосов
/ 24 мая 2018

Вы можете использовать следующие быстрые и грязные grep команды для достижения вашей цели:

$ grep -E 'sample:Recipients>|<sample:user' file | grep -oP '(?<=name=")[^"]*'

ВХОД:

$ cat file 
abc
abc1
<sample:Recipients>
   <sample:user name="******1" guid="8fa4fbaabf904a16ad65449bd7adcba1"/>
   <sample:user name="*******2" guid="f74ebd3310834601a2c22a5dde33c02a"/> 
   <sample:user name="*******3" guid="5fcd2e7775cb42ecbed5ac5dd85e1ca6"/> 
</sample:Recipients>
abc2
abc

ВЫХОД:

$ grep -E 'sample:Recipients>|<sample:user' file | grep -oP '(?<=name=")[^"]*'
******1
*******2
*******3

Пояснения:

Первый grep извлечет строки, содержащие XML, который вы хотите изолировать из вашего входного файла,второй выберет значения из атрибутов с именем name, используя perl regex (?<=name=")[^"]* с положительным взглядом сзади.

Другое быстрое и грязное решение с использованием sed:

$ grep -E 'sample:Recipients>|<sample:user' file | sed -n '/name="/s/.*name="\([^"]*\)".*/\1/gp'
******1
*******2
*******3

Пояснения:

Вы используете sed и обрабатываете линии только при сопоставлениишаблон name= затем вы заменяете всю строку обратной ссылкой на значение имени: \1 (значение атрибута)

ХОРОШЕЕ РЕШЕНИЕ:

вместоgrepping или используя sed просто используйте анализатор xml для анализа вашего вывода xml:

$ cat extract_name.xsl 
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" omit-xml-declation="yes" indent="no"/>
<xsl:template match="/">
  <xsl:for-each select="/*/*/@name">
        <xsl:value-of select="."/><xsl:text>&#xa;</xsl:text>
  </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

$ xsltproc extract_name.xsl <(grep -E 'sample:Recipients>|<sample:user' file) 2>/dev/null
******1
*******2
*******3

Это самый безопасный способ работы, обратите внимание, что 2>/dev/null используется для игнорирования предупреждения пространства именпотому что образец пространства имен не определен правильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...