перенаправить вывод на определенный номер строки

Я хочу grep определенные строки по keyword и перенаправить вывод на определенный номер строки существующего файла.

команда

 grep "key" temp_file >> desired.txt 

Мне нужно, чтобы я мог добавить строки grepped к определенному номеру строки, например, x файла desired.txt

6 Solutions collect form web for “перенаправить вывод на определенный номер строки”

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

 { head -n "$((num_lines_before_insert))" grep key temp_file; sed \$d } <<SOURCE_FILE >desired.txt $( cat <source_file;echo .) SOURCE_FILE 

Таким образом, для большинства оболочек (включая bash и zsh , но не dash или yash ), когда вы получаете << here_document, оболочка создает файл с уникальным именем temp в ${TMPDIR:-/tmp} , exec s it на входе дескриптор файла, который вы указываете, – (или, по умолчанию, всего 0) – и быстро удаляет его. К тому времени, когда он будет использоваться в качестве входных данных для вашей команды, это файл без имени – он не имеет оставшихся ссылок на любую файловую систему и просто ждет, пока ядро ​​его очистит, прежде чем оно полностью исчезнет. Это правильный файл – его данные существуют где-то на диске (или, по крайней мере, в VFS в вероятном случае tmpfs ), и ядро ​​обеспечит его продолжение по крайней мере до тех пор, пока вы не отпустите дескриптор файла.

Таким образом, пока ваша оболочка получает фактический файл поддержки для heredoc – они представляют собой очень безопасные и простые средства обработки временных файлов, потому что они полностью написаны, и все имена файловой системы уже удалены из них, прежде чем вы их прочитаете , Поэтому их данные нельзя подделать, пока вы работаете.

Вышеупомянутый блок сначала записывает временный файл с cat и сохраняет любые / все конечные пустые строки из командной подстановки с помощью echo что добавляет одну строку в хвост файла. Из инструкции { составная команда } вывод трех трех команд записывается в desired.txt – два из которых считывают в свою очередь из heredocument head и хвост исходного файла – и команду grep которая вставляет ваш key .

Я не уверен, что вам это нужно, но я подумал, что важно показать, что вы можете просто и безопасно полностью перезаписать исходный файл с такой последовательностью.

Если ваша оболочка не получает фактический файл для heredocs, вы можете эмулировать то, что ему нравится …

 { set "$$" "${TMPDIR:-/tmp}" "$@" exec <"$2/$( set -C >"$2/$1" cat && echo "$1")" >&1 rm -- "$2/$1";shift 2 head "-n$((before))" grep ... keyfile; cat } <source_file 1<>source_file 

… который гарантирует, что все файлы будут доступны для записи и безопасно назначены файловым дескрипторам, прежде чем предпринимать какие-либо необратимые действия, но также сделает всю очистку файловой системы перед тем, как сделать это.

Вот тест, который я проверил, чтобы продемонстрировать это:

 cd /tmp set "$$" "${TMPDIR:-/tmp}" "$@" seq 5000000 >test printf line\ %s\\n 1 2 3 4 5 >test2 { exec <"$2/$( set -C >"$2/$1" cat && echo "$1")" >&1 rm -- "$2/$1";shift 2 head -n2500000 grep 3 test2;cat } <test 1<>test 

Сначала создавались два файла – один из них назывался /tmp/test который состоял всего из 5 миллионов пронумерованных строк, написанных seq а второй назывался /tmp/test2 который был всего 5 строк, таких как …

 line 1 line 2 line 3 line 4 line 5 

Затем я побежал над этим блоком, потом сделал …

 sed -n '1p;$p;2499999,2500002l' <test wc -l test 

… что, интересно, заняло практически такое же количество времени для выполнения операции вставки и напечатало:

 1 2499999$ 2500000$ line 3$ 2500001$ 5000000 5000001 test 

Итак, вот как это работает:

  1. Перенаправление 1<> важно – он устанавливает флаг O_RDWR на stdout и гарантирует, что по мере того как каждый процесс записывает в файл, он записывает предыдущее содержимое файла. Другими словами, это означает, что ни в каком случае исходный / целевой файл никогда не усекается, а скорее переписывается с головы до хвоста.
  2. Замена команды для exec получает неотложную часть, как только это возможно (или как только я это знаю) . Внутри команды sub noclobber set так, что если "${TMPDIR:-/tmp}/$$" уже существует, то результат расширения в exec <"${TMPDIR:-/tmp}/" который в интерактивной оболочке прекратит весь процесс сразу, или, в сценарии, заставит скрипт выйти со значимой ошибкой, так как оболочка не может exec каталог как stdin.
  3. В пределах команды sub cat копирует source_file в временный файл, который еще не существует, и echo записывает имя в stdout.
  4. Как только все дескрипторы файлов исполняются rm unlink() s, новый временный файл, поэтому его единственным мимолетным заявлением о существовании теперь является < перенаправление, которое оно было просто назначено.
  5. head ищет по 2,5-миллиметровым линиям и записывает первые 2,5-миллилитровые строки source_file. Дело в том, чтобы искать оба файла равными смещениями.
    • Это напомнит, что эта часть может быть более эффективной в том случае, если вновь созданный файл tmp находится на tmpfs, а исходный файл находится на диске, если здесь были отменены операции ввода / вывода и начата запись из файла на диске и написана к файлу в ОЗУ.
    • Если вы хотите сделать это, хотя вам нужно будет выполнить exec <>"$(... head ... <&1 >&0 чтобы сделать файл tmp доступным для чтения / записи и, возможно, использовать head / tail с указанным количеством строк для хвоста. В этом случае число не обязательно должно быть точным – вы можете чередовать ввод аналогичным образом – продвигая смещение только немного за раз. Встроенное read оболочки можно использовать для проверки EOF – или wc может использовать при открытой петле.
    • Это потому, что cat , вероятно, просто повесится на <> stdin, потому что она никогда не увидит EOF.
  6. grep читает некоторые данные из другого файла и записывает их в source_file переписывая только столько байтов, сколько читает из других источников.
  7. cat исправляет любое несоответствие, которое grep может просто вызвать из-за написания того, что осталось от его stdin, до его 1<>source_file .

Не подходит для огромных файлов, но ed может выводить команду и вставлять ее после адресной строки, например:

 ed -s desired.txt <<IN 4r !grep "key" temp_file w q IN 

или, в одной строке:

 printf '%s\n' '4r !grep "key" temp_file' wq | ed -s desired.txt 

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

 ed -s desired.txt <<IN 48r !grep "another_key" another_temp_file 4r !grep "key" temp_file w q IN 

Если desired.txt – очень большой файл, тогда вы можете оптимизировать его. Вероятно, это можно сделать более элегантным на уровне оболочки, но поскольку я не знаком с tcsh я предлагаю что-то, что должно там работать.

 sed -n '1,4p' desired.txt >file.tmp grep "key" temp_file >>file.tmp sed -n '5,$p' desired.txt >>file.tmp mv file.tmp desired.txt 

Здесь awk решение (работает с любой оболочкой, mawk и gawk ):

 awk 'NR==3{ while((getline x<"test_file")>0) { if(x~/key/){print x} } } {print}' desired.txt 

Результат: извлеченная строка будет напечатана в строке 3.

Объяснение: В строке № 3 ( NR==3 ), петля через второй файл ( while((getline x<"test_file")>0) ), и если строка во втором файле содержит «ключ» ( if(x~/key/) ) напечатать эту строку ( {print x} ). Строка от файла desired.txt первого файла должна быть напечатана в любом случае ( {print} )

Я не понимаю, почему каждый пытается сделать проблему из простой задачи?

 sed -i "4a$(grep "key" temp_file)" desired.txt 

(изменение 4 для любого номера строки, который вам нужен)

Или (для многострочного grep вывода)

 grep "key" temp_file > grepped.tmp sed -i '4r grepped.tmp' desired.txt 

$ sed '4 a \

> `grep" ключ "temp_file`" wish.txt

Попробуй это. Вариант a для после строки №. 4. Вы также можете указать опцию i для строки №. 4

Надеюсь, это должно сработать.

  • Событие не найдено в вызове sed в сценарии csh
  • Поиск нескольких вхождений определенного символа в tcsh
  • Понимание команды «grep» показывает разные результаты, чем ожидалось
  • Что случилось с этим csh-файлом?
  • Имеет ли tcsh эквивалент «$ {a: -b}» для назначения переменной по умолчанию, например Bash?
  • setenv из awk в tcsh
  • Переименование файлов дает странный результат в tcsh
  • Как проверить, нет ли строки в tcsh
  • Как установить переменную как идентификатор пользователя
  • Заменить определенный текст в фигурных скобках
  • tcsh, чтобы переместить курсор обратно в предыдущее пространство
  • Linux и Unix - лучшая ОС в мире.