Представьте себе вывод команды вроде
44444
55555
11111
22222
33333
Как я могу вырвать первые N строк (первые две в приведенном выше примере) и добавить их в конце, но без использования временного файла (поэтому только с использованием труб)?
11111
22222
33333
44444
55555
Нечто подобное | sed -n '3,5p;1,2p'
(что явно не работает, так как sed не заботится о порядке команд).
command-line
text-processing
Петр Унак
источник
источник
Ответы:
Просто скопируйте эти строки в буфер удержания (затем удалите их) и, когда в последней строке добавьте содержимое буфера удержания в пространство шаблона:
С
gnu sed
его помощью можно написатьВот еще один способ с ol '
ed
(онr
перенаправляет выводsome command
в текстовый буфер, а затемm
выводит строки1,NUMBER
после последней$
):Обратите внимание, что, как указывалось, они оба потерпят неудачу, если на выходе будет меньше
NUMBER
+1 строки. Более надежный подход (gnu sed
синтаксис):эта строка удаляет только строки в этом диапазоне, если они не являются последней строкой (
$!d
), иначе она перезаписывает пространство шаблона с помощью содержимого буфера удержания (g
) и затемq
использует (после печати текущего пространства шаблона).источник
sed -e '1,NUMBER{H;1h;d;}' -e '$G'
также работает переносимо (обратите внимание, что некоторыеsed
реализации не могут содержать более нескольких килобайт в пространстве удержания, поэтому NUMBER не может быть там слишком большим)sed -e '1,NUMBER{H;1h;d' -e'}' -e '$G'
?-e
заменяет новую строку.d;}
это еще не POSIX, но портативный. Это будет исправлено в следующей спецификации POSIX. См. Austingroupbugs.net/view.php?id=944#c27201,NUMBER{H;1h;d;}
заключается в отсутствии точки с запятой сразу после открывающей скобки. Это могло быть просто ошибкой в SunOS 4.1,sed
чей обходной путь все еще остается у меня в руках 20 лет спустя.awk
Подход:Одно из преимуществ подхода @ don_crissti
sed
состоит в том, что он все еще работает (выводит строки), если на выходе естьn
строки или меньше.источник
\n
на ORS, чтобы он работал с другими разделителями записей (например, вы хотите использовать абзацы и т. Д.).У меня есть
xclip
и с этим это можно сделать следующим образом:Вот его описание:
источник
Способ Perl:
Или то же самое, написанное менее загадочно:
Например:
объяснение
-ne
: прочитайте входной файл / поток построчно и примените скрипт, заданный-e
для каждой строки.$.<3
:$.
номер текущей строки, поэтому измените3
на количество строк, которое вы хотите сместить.$.<3?($f.=$_):print;
: это условный оператор, общий форматcondition ? case1 : case2
, он будет работать,case1
еслиcondition
true иcase2
если false. Здесь, если текущий номер строки меньше 3, он добавляет текущую строку ($_
) к переменной$f
и, если номер строки больше 3, печатает.}{ print $f
:}{
это сокращение от perlEND{}
. Он будет запущен после обработки всех входных строк. На этом этапе мы соберем все строки, которые мы хотим сдвинуть, и напечатаем все те, которые мы хотим оставить в покое, поэтому выведите строки, сохраненные как$f
.источник
perl -ne '$.<3?$f.=$_:print}{print $f
Используйте POSIX
ex
. Да, он предназначен для редактирования файлов, но он будет работать в конвейере.Это может иметь любые произвольные команды, добавленные в начале или конце конвейера, и они будут работать одинаково. Еще лучше, учитывая наличие
/dev/stdin
, это POSIX-совместимый.(Я не знаю,
/dev/stdin
указано ли это в POSIX или нет, но я вижу, что оно присутствует как в Linux, так и в Mac OS X.)Это дает преимущество в удобочитаемости по сравнению с использованием
sed
пробела - вы просто говоритеex
«переместить эти строки в конец», и это так. (Остальные команды означают «печать буфера» и «выход», которые также достаточно читабельны.)NB.
ex
Команда, приведенная выше, не будет выполнена, если в качестве входных данных указано менее 2 строк.Дальнейшее чтение:
источник
Короткий
python
фрагмент:Передайте имя файла в качестве первого аргумента и количество строк для перемещения в качестве второго аргумента.
Пример:
источник
Если вы можете сохранить весь вывод в памяти:
источник
Вот еще один вариант, который требует GNU
sed
:-u
делает GNUsed
небуферизованным, чтобыsed
команда не занимала более 3 строк STDIN. Подстановка команды удаляет пустые строки, так что команда не включает пустые строки в конце вывода, если третья, третья и вторая или третья, вторая и первая строки пусты.Вы также можете сделать что-то вроде этого:
Без
sponge /dev/stdout|
команды не получится с длинными входами.sponge /dev/stdout
также может быть заменен наtac|tac
, даже если это печатает, например,a\ncb
если ввод -a\nb\nc
где\n
перевод строки, или с(x=$(cat);printf %s\\n "$x")
, даже если это удаляет пустые строки с конца ввода. Приведенная выше команда удаляет первую строку, когда количество строк ввода равно одной или двум.источник