Найти номер события sed [duplicate]

Это потому, что s1 и s2 работают только как ссылки на ваши объекты. При назначении s2 = s1 вы назначаете только ссылку, что означает, что оба будут указывать на один и тот же объект в памяти (объект, который имеет текущий текст «первым»).

Когда вы сейчас устанавливаете сеттер, на s1 или s2, оба будут изменять один и тот же объект.

8
задан Cœur 25 April 2017 в 17:09
поделиться

5 ответов

Это может сработать для вас (GNU sed):

'sed -n '/category/{:a;N;/done/!ba;x;s/^/x/;/^x\{3\}$/{x;p;q};x}' file

Отключить автоматическую печать с помощью параметра -n. Соберите линии между category и done. Храните счетчик в удержании и когда он достигает 3, напечатайте коллекцию в пространстве шаблонов и закройте.

Или, если вы предпочитаете awk:

awk  '/^category/,/^done/{if(++m==1)n++;if(n==3)print;if(/^done/)m=0}'  file
7
ответ дан potong 17 August 2018 в 10:17
поделиться
  • 1
    sed - отличный инструмент для простых замещений на одной линии. Для чего-либо еще просто используйте awk или вы обнаружите, что минимальные требования меняются (например, распечатывают номера строк), требуется полная перезапись вашего скрипта, возможно, на другом языке. Выполнение чего-либо в sed, которое требует больше, чем "s" и "g" команды - пустая трата времени. – Ed Morton 8 November 2012 в 15:25
  • 2
    awk-скрипт будет продолжать печатать после «done & quot; если tes = xt между сделанными и следующей категорией. Он также напечатает неверный блок, если категория может существовать без выполнения. не знаю, что будут делать сценарии sed. – Ed Morton 8 November 2012 в 16:52
  • 3
    @EdMorton Я считаю, что печать сужается между category и done, если нет done, это может быть то, что требует пользователь. – potong 8 November 2012 в 17:30
  • 4
    Попробуйте его с файлом с 2 "категориями" линии перед первым «выполнением». Он будет печатать блок 2-й категории и gt, а не третий. – Ed Morton 8 November 2012 в 17:42
  • 5
    просто любопытно: почему? он тестирует одно и то же условие несколько раз и не будет работать, если ваш входной файл немного изменится. Если вы довольны решением, которое работает только с размещенным форматом ввода, решение @ sputnik намного более кратким. – Ed Morton 8 November 2012 в 19:56
awk -v tgt=3 '
/^category$/ { fnd=1; rec="" }

fnd {
   rec = rec $0 ORS
   if (/^done$/) {
      if (++cnt == tgt) {
         printf "%s",rec
         exit
      }
      fnd = 0
   }
}
' file
1
ответ дан Ed Morton 17 August 2018 в 10:17
поделиться

Попробуйте сделать это:

 awk -v n=3 '/^category/{l++} (l==n){print}' file.txt

Или еще cryptic:

awk -v n=3 '/^category/{l++} l==n' file.txt

Если ваш файл большой:

awk -v n=3 '/^category/{l++} l>n{exit} l==n' file.txt
5
ответ дан Gilles Quenot 17 August 2018 в 10:17
поделиться
  • 1
    Извините, скажем, что начало и конец - это не одно и то же слово, я хочу, чтобы третье появление того, что происходит между категорией и сделано. – Dan Lawless 8 November 2012 в 05:04
  • 2
    /^category/ означает строку, начинающуюся с «категории», она действительно отличается от категории , содержащей . Поэтому нет необходимости в каких-либо модификациях, сценарий по-прежнему работает AS IS. – Gilles Quenot 8 November 2012 в 06:16
  • 3
    Это будет работать с размещенным образцом ввода, но не будет работать, если могут быть случаи категории без выполнения или текст между сделанными и категориями. – Ed Morton 8 November 2012 в 15:32

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

sed -n '/^category/ { x; s/^/\x0/; /^\x0\{3\}$/ { x; :a; p; /done/q; n; ba }; x }' file.txt

Результаты:

category
3
r
d
done

Объяснение:

Отключить по умолчанию печать с помощью переключателя -n. Сопоставьте слово «категория» в начале строки. Поменяйте пространство шаблонов пространством удержания и добавьте нулевой символ в начало шаблона. В примере, если шаблон затем содержит два ведущих нулевых символа, вытащите шаблон из пространства пробелов. Теперь создайте цикл и распечатайте содержимое пространства шаблонов до тех пор, пока не будет сопоставлен последний шаблон. Когда этот последний шаблон найден, sed закроется. Если он не найден, sed продолжит читать следующую строку ввода и продолжить в своем цикле.

1
ответ дан Steve 17 August 2018 в 10:17
поделиться
  • 1
    Я бы хотел, чтобы он печатал третье вхождение, но только если второе вхождение содержало слово «awk». Как мне изменить эту команду sed для этого? В awk я просто создаю & quot; prevRec & quot; для сохранения предыдущей записи и добавления if (prevRec ~ /awk/) перед печатью. – Ed Morton 8 November 2012 в 15:30

С помощью GNU awk вы можете установить разделитель записи в регулярное выражение:

<file awk 'NR==n+1 { print rt, $0 } { rt = RT }' RS='\\<category' ORS='' n=3

Выход:

category 
3
r
d
done

RT - разделитель совместимых записей. Обратите внимание, что запись относительно n будет отключена на единицу, так как первая запись относится к тому, что предшествует первому RS.

Редактировать

Согласно комментарию Эда, это будет не работают, когда у записей есть другие данные между ними, например:

category
1
s
t
done
category
2
n
d
done

foo

category
3
r
d
done

bar
category
4
t
h
done

. Один из способов обойти это - очистить вход с помощью второго (или первого) awk:

<file awk '/^category$/,/^done$/' |
  awk 'NR==n+1 { print rt, $0 } { rt = RT }' RS='\\<category' ORS='' n=3

Выход:

category 
3
r
d
done

Редактировать 2

Поскольку Ed отметил в комментариях, указанные выше методы не ищут окончания шаблон. Один из способов сделать это, который не был рассмотрен другими ответами, - с getline (обратите внимание, что существуют некоторые оговорки с awk getline):

<file awk '
  /^category$/ {
    v = $0
    while(!/^done$/) { 
      if(!getline) 
        exit
      v = v ORS $0
    }
    if(++nr == n) 
      print v
}' n=3

В одной строке:

<file awk '/^category$/ { v = $0; while(!/^done$/) { if(!getline) exit; v = v ORS $0 } if(++nr == n)  print v }' n=3
0
ответ дан Thor 17 August 2018 в 10:17
поделиться
  • 1
    который будет печатать текст между вхождениями категории слова, а не между категорией и выполненным. В размещенном входе это не имеет значения, но в целом это может быть, например, если f может быть другим текстом между сделанным и категорией или вхождениями категории без соответствующего завершения. – Ed Morton 8 November 2012 в 15:23
  • 2
    @EdMorton: Верно. Одно из возможных исправлений - сначала очистить вход, см. Редактирование. – Thor 9 November 2012 в 09:43
  • 3
    Он все равно потерпит неудачу и напечатает вторую запись вместо 3-го, если вы добавите «категорию», перед первым "выполнением" в вашем примере ввода, например. между "s" и "t" линий. – Ed Morton 9 November 2012 в 16:16
  • 4
    @EdMorton: Верно, я вижу вашу точку, окончательный шаблон не ищет. Я добавил альтернативу getline, которая выполняет поиск done. – Thor 10 November 2012 в 15:49
  • 5
    IMHO не-getline-версия, которую я опубликовала, проще и не содержит всех оговорок getline (см. awk.info/?tip/getline ). Я ожидаю, что вы опубликовали это как отличие от других решений, но для выгоды от OPs я думаю, что стоит упомянуть, что он поставляется с некоторым багажом. – Ed Morton 12 November 2012 в 21:31
Другие вопросы по тегам:

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