Как добавить 10 строк из файла (file2) в другой после 2 строк (file1)?

/ dev / vcs [a] даст вам только последний полный экран, даже если вы прокрутили вверх, но выбор ioctl () s, используемый gpm , позволит вам сбросить текущий отображаемый экран даже при прокрутке вверх.

Итак, вы можете:

sleep 3; perl -e '
  require "sys/ioctl.ph";
  # copy:
  ioctl(STDIN, &TIOCLINUX, $arg = pack("CS5", 2, 1, 1, 80, 25, 2));
  # paste:
  ioctl(STDIN, &TIOCLINUX, $arg = "\3")'; cat > file

Настроить 80 и 25 на вашу фактическую ширину и высоту экрана.

спящий режим 3 дает вам время для прокрутки вверх (с помощью Shift + PageUP ) до фактического экрана, который вы хотите сбросить. cat> file перенаправляет вставку в файл . Завершите его, нажав Ctrl + D .

Подробнее см. console_ioctl (4) .

Если у вас установлен и запущен gpm , вы можете сделать этот выбор с помощью мыши.

Прокрутка и выбор виртуальной консоли Linux очень ограничены и довольно раздражают (в том смысле, что при переключении консоли вы теряете всю прокрутку). Забегая вперед, я бы посоветовал вам использовать в нем такие вещи, как GNU screen или tmux (я лично использую их в еще более функциональных терминалах). С их помощью вы можете иметь более крупные прокрутки с возможностью поиска и легко выгружать их в файлы (и даже регистрировать весь вывод терминала, а также все другие полезности, которые поставляются с этими терминальными мультиплексорами).


Что касается автоматизации процесса сброса всего буфера прокрутки, это должно быть возможно при некоторых условиях, но довольно сложно, поскольку API очень ограничен. Существует недокументированный ioctl (TIOCLINUX, subcode = 13) для прокрутки текущей виртуальной консоли с некоторым смещением (отрицательное для прокрутки вверх, положительное для прокрутки вниз).

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

Я также нахожу поведение прокрутки ioctl неустойчивым (по крайней мере, с консолью VGA), когда прокрутка менее чем на 4 строки работает только изредка.

Приведенный ниже сценарий, кажется, работает для меня на консолях с кадровым буфером (а иногда и на VGA) при условии, что буфер обратной прокрутки не содержит последовательностей одинаковых строк длиннее одного экрана плюс одна строка.

Это довольно медленно, поскольку выполняется прокрутка по одной строке за раз, и при чтении каждого дампа экрана требуется 10 мсек ожидания eof.

Для использования как тот-скрипт> файл из виртуальной консоли.

#! /usr/bin/perl
require "sys/ioctl.ph";
($rows,$cols) = split " ", `stty size`;
$stty = `stty -g`; chomp $stty;
system(qw(stty raw -echo icrnl min 0 time 1));

sub scroll {
  ioctl(STDIN, &TIOCLINUX, $arg = pack("Cx3l", 13, $_[0])) or die "scroll: $!";
}
sub grab {
  ioctl(STDIN, &TIOCLINUX, $arg = pack("CS5", 2, 1, 1, $cols, $rows, 2)) or die "copy: $!";
  ioctl(STDIN, &TIOCLINUX, $arg = "\3") or die "paste: $!";
  return <STDIN>;
}
for ($s = 0;;$s--) {
  scroll $s if $s;
  @lines = grab;
  if ($s) {
    last if "@lines" eq "@lastlines";
    unshift @output, $lines[0];
  } else {
    @output = @lines;
  }
  @lastlines = @lines;
}
print @output;
exec("stty", $stty);
4
16.12.2018, 13:53
1 ответ

Вы можете использовать ed!

ed -s file1 <<< $'2r !head -10 file2\nw\nq'

Это говорит ed редактировать файл1 тремя командами:

  1. в строке 2, прочитайте вывод команды head -10 file2и вставьте его
  2. wзаписать файл
  3. qв комплекте

В GNU sed (с использованием расширения e, которое направляет ввод из команды оболочки):

sed -i '3e head -10 file2' file1

Расширенное решение для перебора файла2

Приведенный ниже сценарий представляет собой цикл for, который повторяет идею edстолько раз, сколько блоков transcr_в файле1. Каждый раз в цикле мы вычисляем три элемента:

  1. номер строки для edначала чтения из файла1
  2. номер строки для sedначала чтения из файла2
  3. номер строки для sedостановки чтения из файла2

Пункт #1 более четко прописан как :10*(N-1) + 2*N, который я сократил до 12*N - 10.

Элементы с #2 и #3 более четко обозначены как 10*(N-1) + 110*N, которые я сократил до 10*N - 910*N.

Я заменил команду headна более гибкую и мощную команду sedдля выделения блоков строк из файла2.

Это приведет к перезаписи файла 1 timesраз по мере прохождения цикла.

# how many times we need to insert blocks
times=$(grep -c transcr_ file1)
for((index=1;index <= times; index++));
do
  printf "%dr !sed -n %d,%dp file2\nw\nq\n" $((12 * index - 10)) $((10 * index - 9)) $(( 10 * index ))  |
    ed -s file1
done
11
27.01.2020, 20:47

Теги

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