Эту проблему на самом деле проще всего решить ed, так как это текстовый редактор, а не потоковый процессор. Используя ed, вы не должны сохранить все строки файла в массив, например, так как он уже делает это для вас.
# Create test file
~> printf "%s\n" aaaaaa bbbbbb cccccc dddddd eeeeee >test.txt
~> cat test.txt
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
# Use ed to open the file, move the last line after the first, save, and quit
~> printf "%s\n" '$m1' wq | ed test.txt
35
35
~> cat test.txt
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
sed '$x;1!H;1p;$!d;x;s/\n//
' <<\IN
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
IN
... это будет Hстареть каждую строку, которая !не первая, а первая она pнабирает. В $последней строке он xизменяет удержание и образует пробелы перед тем, как Hвыполнить старую процедуру, в которой сохраненные строки добавляются к последней строке, а затем dвыбирается из всех строк, которые !не являются $последними.
В $последней строке он xснова меняет пробелы, s///убирает первый \nсимвол ewline - который заботится о дополнительном добавлении в строке 2 - затем автоматически печатает лот.
ВЫВОД:
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
без использования буфера Hold:
cat <<\IN >infile
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
IN
... просто чтобы сохранить пример в реальном файле ...
sed '1p;$!d;r infile' <infile | sed '3d;$d'
Который перенаправляет <infileна первый sed-х stdin, которые только prints первой строки перед deleting от выхода всех линий , которые !не в $последней очереди . Последняя строка autoprinted, но это также единственная линия , на которой выполняется последняя команда - которая является rEAD вне цельной infileснова к stdout. Все это передается по каналу |во вторую, sedкоторая затем должна только dвыбрать из своего выхода свою третью и последнюю строки ввода, чтобы завершить перестановку.
Вы сохраняете каждую строку в aмассиве, затем печатаете массив в нужном вам порядке (1-я строка, последняя ( NR) и от 2 до предпоследней.
Используя комбинацию головы / хвоста и седа:
~$ head -1 f;tail -1 f;sed '1d;$d' f
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
Выведите первую строку, последнюю, а с помощью sed удалите первую и последнюю.
Только с помощью sed мне удалось найти только эту команду. Я уверен, что есть лучшие способы:
~$ sed '${p;x;s/^\n//;p};2,${H;d}' f
aaaaaa
eeeeee
bbbbbb
cccccc
dddddd
Если это первая строка, выведите ее (по умолчанию).
Со второй строки поместите его в буфер удержания ( H) и удалите из пространства шаблона ( d). И если это последняя строка, напечатайте его ( p), затем получите буфер удержания ( x), удалите пустую строку ( s/^\n//) и напечатайте ее ( p).
awk
решения, вы большойsed
поклонник или, возможно, вы написалиsed
? ;-)awk
- я никогда не пробовал. может быть, когда-нибудь ...Наивный подход с использованием awk:
Вы сохраняете каждую строку в
a
массиве, затем печатаете массив в нужном вам порядке (1-я строка, последняя (NR
) и от 2 до предпоследней.Используя комбинацию головы / хвоста и седа:
Выведите первую строку, последнюю, а с помощью sed удалите первую и последнюю.
Только с помощью sed мне удалось найти только эту команду. Я уверен, что есть лучшие способы:
Если это первая строка, выведите ее (по умолчанию).
Со второй строки поместите его в буфер удержания (
H
) и удалите из пространства шаблона (d
). И если это последняя строка, напечатайте его (p
), затем получите буфер удержания (x
), удалите пустую строку (s/^\n//
) и напечатайте ее (p
).источник
sed
части будет что-то вродеhead -n -1 f | tail -n +2
.-1
синтаксис дляhead
не является переносимым.С perl:
С awk:
ВЫВОД
источник