Как получить несколько строк из файла regex?

Команда ls значения по умолчанию к ls .: Перечислите все записи в текущем каталоге.

Команда ls * означает 'выполненный ls на расширении * шаблон оболочки'

* шаблон обрабатывается оболочкой и расширяется до всех записей в текущем каталоге, кроме тех, которые запускаются с a .. Это пойдет один уровень глубоко.

Интерпретация двойных или тройных * шаблоны зависят от фактической используемой оболочки.

* подстановочный знак, который соответствует 0 или больше символам. Некоторые современные оболочки рекурсивно вызовут в подкаталоги наблюдение ** шаблон.

10
27.04.2014, 23:31
6 ответов

Если у Вас есть GNU grep, установил Вас, мог бы сделать многострочный поиск путем передачи в -P (perl-regex) флаг и активация PCRE_DOTALL с (?s)

grep -oP '(?s)<tag1>(?:(?!tag1).)*?foo(?:(?!tag1).)*?</tag1>' file.txt
<tag1>
<tag2>foo</tag2>
</tag1>

Если вышеупомянутое не работает над Вашей платформой, попытайтесь передать -z отметьте, кроме того, это вынуждает grep рассматривать NUL как разделитель строки, заставляя весь файл быть похожим на одну строку.

grep -ozP '(?s)<tag1>(?:(?!tag1).)*?foo(?:(?!tag1).)*?</tag1>' file.txt
7
27.01.2020, 20:01
  • 1
    Это не дает вывода в моей системе при выполнении на файле OP в качестве примера. –  terdon♦ 21.10.2013, 18:24
  • 2
    Работы для меня. +1. Спасибо за (?s) –  Nathan Wallace 21.10.2013, 18:30
  • 3
    @terdon подсказки, что выполняет версия GNU grep Вы? –  iruvar 21.10.2013, 18:42
  • 4
    @1_CR (GNU grep) 2.14 на Debian. Я скопировал пример операции в секунду, как (добавление только заключительной новой строки) и выполнил Ваш grep на нем, но не получил результатов. –  terdon♦ 21.10.2013, 18:47
  • 5
    @slm, я нахожусь на pcre 6.6, GNU grep 2.5.1 на RHEL. Вы возражаете пробовать grep -ozP вместо grep -oP на Ваших платформах? –  iruvar 21.10.2013, 19:51

Ответ @jamespfinn будет работать отлично, если Ваш файл будет так же прост как Ваш пример. Если у Вас есть более сложная ситуация где <tag1> мог охватить больше чем 2 строки, Вам будет нужен немного более сложный прием. Например:

$ cat foo.xml
<tag1>
 <tag2>bar</tag2>
 <tag3>baz</tag3>
</tag1>
<tag1>

 <tag2>foo</tag2>
</tag1>

<tag1>
 <tag2>bar</tag2>

 <tag2>foo</tag2>
 <tag3>baz</tag3>
</tag1>
$ perl -ne 'if(/<tag1>/){$a=1;} 
            if($a==1){push @l,$_}
            if(/<\/tag1>/){
              if(grep {/foo/} @l){print "@l";}
               $a=0; @l=()
            }' foo.xml
<tag1>

  <tag2>foo</tag2>
 </tag1>
<tag1>
  <tag2>bar</tag2>

  <tag2>foo</tag2>
  <tag3>baz</tag3>
 </tag1>

Сценарий жемчуга обработает каждую строку Вашего входного файла и

  • if(/<tag1>/){$a=1;} : переменная $a установлен на 1 если открывающий тэг (<tag1>) найден.

  • if($a==1){push @l,$_} : для каждой строки, если $a 1, добавьте что строка к массиву @l.

  • if(/<\/tag1>/) : если текущая строка соответствует закрывающему тэгу:

    • if(grep {/foo/} @l){print "@l"} : если какая-либо из строк сохраняется в массиве @l (это строки между <tag1> и </tag1>) соответствует строке foo, распечатайте содержание @l.
    • $a=0; @l=() : освободите список (@l=()) и набор $a назад к 0.
2
27.01.2020, 20:01
  • 1
    Это работает хорошо кроме случая, где существует больше чем один <tag1>, содержащий "нечто". В этом случае это печатает каждую вещь с начала первого <tag1> в конец последнего </tag1>... –  Den 23.10.2013, 15:55
  • 2
    @den я протестировал его с примером, показанным в моем ответе, который содержит 3 <tag1> с foo и это хорошо работает. Когда это перестало работать для Вас? –  terdon♦ 23.10.2013, 16:01
  • 3
    это чувствует себя настолько неправильным, анализируя xml использование regex :) –  Braiam 28.04.2014, 02:58

Если Ваш файл структурирован точно, поскольку Вы показали выше, Вы могли использовать-A (строки после) и-B (строки прежде) флаги для grep..., например:

$ cat yourFile.txt 
<tag1>
 <tag2>bar</tag2>
</tag1>
<tag1>
 <tag2>foo</tag2>
</tag1>
$ grep -A1 -B1 bar yourFile.txt 
<tag1>
 <tag2>bar</tag2>
</tag1>
$ grep -A1 -B1 foo yourFile.txt 
<tag1>
 <tag2>foo</tag2>
</tag1>

Если Ваша версия grep поддержки это, Вы могли также использовать более простое -C (для контекста) опция, которые печатают окружение N строки:

$ grep -C 1 bar yourFile.txt 
<tag1>
 <tag2>bar</tag2>
</tag1>
0
27.01.2020, 20:01
  • 1
    Спасибо, но нет. Это - только пример, и реальный материал смотрит довольно непредсказуемый ;-) –  Den 21.10.2013, 18:10
  • 2
    Это не находит тег с нечто в нем, это просто находит нечто и отображается, строки номера –  Nathan Wallace 21.10.2013, 18:28
  • 3
    @NathanWallace да, который является точно, что OP просил, этот ответ работы отлично в случае, данном в вопросе. –  terdon♦ 21.10.2013, 18:46
  • 4
    @terdon это нисколько не, что спрашивает вопрос. Кавычка: "Я хотел бы читать <tag1>, если он содержит нечто где-нибудь в нем". Это решение похоже, "Я хотел бы считать 'нечто' и 1 строку контекста независимо от того, где 'нечто' появляется". После Вашей логики одинаково действительный ответ на этот вопрос был бы tail -3 input_file.xml. Да это работает на этот определенный пример, но это не полезный ответ на вопрос. –  Nathan Wallace 21.10.2013, 20:45
  • 5
    @NathanWallace, которым моя точка была то, что OP конкретно указал это, не является допустимым форматом XML, в этом случае, возможно, было достаточно распечатать строки N вокруг строки, которую ищет OP. С доступной информацией этот ответ был достаточно достоин. –  terdon♦ 21.10.2013, 21:25

Если вы сделаете то, что описано выше, то, учитывая показанные данные, до последней линии очистки, вы должны работать с пространством шаблона [117100]sed[117101], которое выглядит следующим образом:

Вы можете распечатывать пространство шаблона в любое время с помощью [117102]l[117103]ook. Затем вы можете обратиться к [117104]\n[117105] символам.

C:\Python27\python
Покажет вам каждую строку [117106]sed[117107] обрабатывает ее на этапе вызова [117108]l[117109].

Итак, я только что протестировал ее, и ей понадобился еще один [117110]\backslash[117111] после [117112],запятой[117113] в первой строке, но в остальном все работает как есть. Здесь я поместил ее в [117114]_sed_function[117115], чтобы можно было легко вызвать ее для демонстрационных целей на протяжении всего ответа: [117116](работает с включенными комментариями, но здесь удалены для краткости)

Теперь мы переключим [117118]p[117119] на [117120]l[117121], чтобы посмотреть, с чем мы работаем по мере разработки нашего скрипта и удалить нон-оп демонстрацию [117122]? [117123] так что последняя строчка нашего [117124]sed 3<<\SCRIPT[117125] выглядит так:

Тогда я запущу ее снова:

Хорошо! Итак, я был прав - это хорошее чувство. Теперь давайте перетасуем наши [117126]l[117127]ook вокруг, чтобы увидеть линии, которые он втягивает, но удаляет. Мы удалим наш текущий [117128]l[117129] и добавим один к [117130]!{блок}[117131] так, чтобы выглядело:

Function SearchReplace()
    Dim db As DAO.Database, rs As DAO.Recordset, sSQL As String, sData As String

    'Get the record set we wish to modify
    Set db = CurrentDb
    sSQL = "SELECT * FROM Table1"                     '[replace table name]
    Set rs = db.OpenRecordset(sSQL)

    'iterate through each record
    While Not rs.EOF

        'check for the matching sub string in the field "data"
        sData = rs![Data]                             '[replace target field]
        If InStr(1, sData, "~~") Then

            'modify the data string, replacing "~~" with a line break
            sData = Replace(sData, "~~", vbCrLf)

            'escape any ' characters to avoid errors and/or injection
            sData = Replace(sData, "'", "''")

            'update the table with the modified string'
            sSQL = "UPDATE Table1" & _                '[replace table name]
                   " SET data='" & sData & "'" & _     '[replace target field]
                   " WHERE [ID] = " & rs![ID]          '[replace PK field]
            db.Execute sSQL

        End If

        rs.MoveNext
    Wend

    'destroy record set to be tidy
    rs.Close
    Set rs = Nothing

End Function
Это то, как выглядит перед тем, как мы его сотрем.
И последнее, что я хочу вам показать, это [117132]H[117133]старое пространство по мере того, как мы его создадим. Есть пара ключевых концепций, которые, надеюсь, я смогу продемонстрировать. Поэтому я снова удаляю последний [117134]l[117135]ook и изменяю первую строку, чтобы добавить взгляд в [117136]H[117137]старое пространство в конце:

H[117139]старое пространство [117140]выживает[117141] циклы строк - отсюда и название. Так что люди часто спотыкаются - хорошо, что [117142]I[117143] часто спотыкаются - это то, что его нужно удалить после того, как вы его используете. В этом случае я меняю только e[117144]x[117145] один раз, так что пространство удержания [117146] становится [117147] пространством паттерна и наоборот, и это изменение также [117148] выдерживает линейные циклы.

UPDATE Table1 
SET data = Replace([data],"~~",Chr(13) + Chr(10));

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

Которое просто выбирает каждый символ и удаляет его. Я не могу использовать [117150]d[117151], потому что это закончило бы мой текущий цикл строк, и следующая команда не завершилась бы, что практически уничтожило бы мой сценарий.

Это работает подобно [117152]H[117153], но он [117154]перезаписывает [117155], так что я только что скопировал мое пустое пространство для шаблонов поверх верхней части пространства для шаблонов, фактически удалив его. Теперь я могу просто: аут.

И так я пишу [117156]sed[117157] сценарии.[116697]

3
27.01.2020, 20:01
[116759]Вот [117258]sed[117259] альтернатива:

Explanation

-n[117669] означает, что не печатайте строки, если не дано указание.

/

            +---------------------------+            +--------------------------+
            |Answer question            |            | ????                     |
            |---------------------------|            |--------------------------|
            | eat pizza                 |            | ????                     |
            |                           |+---------->|                          |
            |                           |            |                          |
            |                           |            |                          |
            |                           |            |                          |
            |                           |            |                          |
            |                           |            |                          |
            +---------------------------+            +---------+----------------+
                                                               |
                   +-------------------------+                 |
                   | PROFIT!                 |                 |
                   |-------------------------|                 |
                   |                         |                 |
                   |                         |-----------------+
                   |                         |
                   |                         |
                   |                         |
                   |                         |
                   +-------------------------+
:x[117673] - это метка, позволяющая перейти к этой точке позже

N[117675] добавляет следующую строку в пространство шаблона (активный буфер).

mysqldump -u user -p databasename > dump.sql

/<\/tag1/!b x[117677] означает, что если текущее пространство шаблона не содержит закрывающего тега, то ответвление к метке [117678]x[117679], созданной ранее. Таким образом, мы продолжаем добавлять строки в пространство паттерна до тех пор, пока не найдем наш закрывающий тег.

scp dump.sql user@remotehost.ip:

/foo/p[117681] означает, что если текущее пространство паттерна совпадает с [117682]foo[117683], это должно быть напечатано.

mysql -u user -p databasename < dump.sql

1
27.01.2020, 20:01
[116765] Вы могли бы сделать это с помощью GNU awk, я думаю, рассматривая конечную метку как [117274] разделитель записей [117275], например. для известной конечной метки [117276][117277]:

или более широко (с регексом для конечной метки)enter image description here

Тестирование на @terdon's [117278]foo.xml[117279]:

1
27.01.2020, 20:01

Теги

Похожие вопросы