Выбор текста в Unix, используя SED

Для более простого однострочного варианта вы можете использовать find опцию -ls. Оказывается, в большинстве случаев размер файла находится в седьмой колонке списка (поэтому измените 7 в конце команды, если это не так):

find . -type f -mtime +10 -ls | sort -n -r -k7
2
21.09.2018, 08:01
4 ответа

Использование только sed:

<infile sed 's/expected/\n&/;s/.*\n//;s/actual/\n&/;s/\nactual.*//'

Пояснение:

  • s/expected/\n&/Поместите новую строку (делит )перед expected.
  • s/.*\n//Удалите направляющую линию, созданную предыдущей командой.
  • s/actual/\n&/Поместите новую строку (делит )перед actual.
  • s/\nactual.*//Удалите созданную выше строку, начинающуюся с actual.

Учтите, что выше будет сгенерирована пустая строка, если actualнаходится в начале строки. Если этой пустой строки нужно избежать, используйте:

<infile sed 's/expected/\n&/;s/.*\n//;/^actual/d;s/actual.*//'

Также обратите внимание, что приведенная выше команда (s )сохранит без изменений все строки, которые не соответствуют ни expected, ни actual, а затем будут напечатаны.
Чтобы избежать этого, добавьте /expected\|actual/!dкак это:

<infile sed '/expected\|actual/!d;s/expected/\n&/;s/.*\n//;/^actual/d;s/actual.*//'

Если требуется диапазон строк между expectedи actual, но с удалением завершающей строки, содержащей actual, используйте:

<infile sed '/^expected/!{s/expected/\n&/};/^actual/!{s/actual.*/\n&/}' |  
        sed '/expected/,/actual/!d;/actual/d'
0
27.01.2020, 22:08

Не слишком элегантно и неэффективно, но со своей задачей справляется

sed 's/actual/\n&/' file | sed -n '/expected/,/actual/p' | sed '$d'
       expected collection contained:  [{"id"=>18646, "state"=>"available", "salesEndAtUtc"=>"2018-09-22T00:00:00.000Z",

Возможно, немного лучше (с GNUsed):

sed -n '/expected/,$ {s/actual.*$//; p; T; q; } ' file

Если команда Tнедоступна, попробуйте

sed -n '/expected/,$ {s/actual.*$//; p; tL; b; :L; q; } ' file
2
27.01.2020, 22:08

Похоже, вы пытаетесь разобрать JSON с помощью sed. Не хорошая идея. Используйте , если возможно.

Тем не менее, вы можете захлебнуть весь файл в память, и провести по нему поиск и замену:

$ cat file
foo
bar
> |e|build_event_details_json(e) })
       expected collection contained:  [
       {"id"=>18646,
       "state"=>"available",
       "salesEndAtUtc"=>"2018-09-22T00:00:00.000Z",
       actual collection contained:    [
       {"id"=>18646
baz
qux

$ sed -n 'H;${g;s/.*\(expected.*\)actual.*/\1/p}' file
expected collection contained:  [
       {"id"=>18646,
       "state"=>"available",
       "salesEndAtUtc"=>"2018-09-22T00:00:00.000Z",

Обратите внимание, что это приведет к выводу из последнего «ожидаемого» в последнего , следующего за «фактическим» из-за жадности квантора *

$ cat file
foo
expect1
bar
> |e|build_event_details_json(e) })
       expected collection contained:  [
       {"id"=>18646,
       "state"=>"available",
       "salesEndAtUtc"=>"2018-09-22T00:00:00.000Z",
       actual collection contained:    [
       {"id"=>18646
baz
actual2
qux

$ sed -n 'H;${g;s/.*\(expected.*\)actual.*/\1/p}' file
expected collection contained:  [
       {"id"=>18646,
       "state"=>"available",
       "salesEndAtUtc"=>"2018-09-22T00:00:00.000Z",
       actual collection contained:    [
       {"id"=>18646
baz
0
27.01.2020, 22:08

Думаю, так и должно быть:

 sed -n '/expected.*actual/{s/actual.*//;p;n};
         /expected/,/actual/{s/actual.*//;p}' input

Если строка содержит как начальный, так и конечный маркеры, отбросить все после конечного маркера и прочитать следующую строку. В противном случае напечатайте что-либо между строками, содержащими начальный и конечный маркеры, снова отбрасывая все после конечного маркера.

0
27.01.2020, 22:08

Теги

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