Скопировать все строки между %packages и %end из файла1 в файл2:
awk '$1=="%end" {f=0;next} f{print;next} $1=="%packages" {f=1}' file1 >>file2
Это решение предназначено для удаления строк %packages и %end. (Если вы хотите, чтобы эти строки также были перенесены, ниже приведено еще более простое решение)
Поскольку awk
неявно перебирает все строки в файле, вышеуказанные команды применяются к каждой строке в файле file1
. Она использует флаг f
, чтобы определить, находимся ли мы в секции пакетов file1
. Каждая строка в секции пакетов выводится в stdout, который перенаправляется в file2
.
Рассмотрим команды awk
, по очереди:
$1=="%end" {f=0;next}
Эта команда проверяет, начинается ли строка с %end
. Если это так, то флаг f
устанавливается на ноль, и мы переходим к строке next
.
f{print;next}
Эта команда проверяет, не является ли флаг f
ненулевым. Если он ненулевой, то строка выводится и мы переходим к следующей строке.
$1=="%packsages" {f=1}
Эта команда проверяет, начинается ли строка с %packsages
. Если да, то устанавливается флаг f
, чтобы строки после него были выведены.
Вышеуказанное исключает маркерные строки %-пакетов и %-концовки. Если вы хотите, чтобы они были включены, используйте:
awk '/^%packages/,/^%end/ {print}' file1 >>file2
]Самое простое для понимания:[
] [grep -A 1000 '%packages' xx | grep -B 1000 '%end'
]
[]Первая часть ищет []%-пакеты[
] и печатает 1000 строк (включая совпадающую строку) []A[] после нее.[
]Вторая часть после трубы: Ищет []%end[
] и печатает все 1000 строк (включая совпадающую) []B[] efore.[
]Если в файле более 1000 строк, измените 1000 на большее число.[
] []А если вы хотите, чтобы []только[] совпадали со строками, которые не имеют ничего, кроме шаблона поиска, включите в него начало и конец регресса, i. e.[
] [grep -A 1000 '^%packages$' xx | grep -B 1000 '^%end$'
]
[]Если вы не хотите, чтобы совпадающие линии были включены, добавьте еще одну трубу:[
] [grep -A 1000 '^%packages$' xx | grep -B 1000 '^%end$' | grep -v -e '^%packages$' -e '^%end$'
]
[]где []-e[
] можно использовать для указания нескольких шаблонов поиска, а []-v[
] используется для инвертирования смысла совпадения, для выделения несовпадающих линий.[
]Помимо awk, еще одно решение для рассмотрения - это sed:[
] [sed -n '/%packages/,/%end/ w file2' file1
]
[]разбивка по порядку появления:[
]
[]sed[
] сама по себе, очевидно, с последующим открытием []'[
]. Это говорит обо всём, начиная с этого момента и заканчивая закрытием []'[
], является аргументом/командой к самому соблазнению. Всё после этого вводится (или выводится, если используется перенаправление >file)[
][]-n[
] Suppress print. Без него будет напечатано всё содержимое файла1, при этом дважды будет напечатан соответствующий текст[
][]/pattern1/,/pattern2/[
] Свойство определяет границы диапазона для соответствия[
][]w file[
] Write to file (Запись в файл). Должен быть последний аргумент, за которым следует имя файла (или /path/to/file if not in current dir)[
]Наконец, после закрытия сингла []'[
] у нас есть входной файл.[
]Два заключительных примечания: [
] []1.некоторые предпочитают использовать перенаправление для входного файла, поэтому заключительная команда выглядит так:[
] [sed -n '/%packages/,/%end/ w file2' <file1
]
[]Преимуществом является большая ясность - очевидно, откуда вы получаете информацию.
Аналогично, вместо использования []w file[
] вы можете перенаправить вывод > file :[
sed -n '/%packages/,/%end/ p' <file1 >file2
]
[]В этом случае мы добавляем []p[
], чтобы распечатать совпадение (переопределение -n для выбора)[
]Однако, sed может работать с несколькими входными файлами:[
] [sed -n '/%packages/,/%end/ w file-final' file1 file2 file3
]
[]и использование перенаправления имеет тенденцию ослеплять пользователей к этой возможности.[
] []2.вышеприведенные совпадения включают в себя стартовую и конечную строки, так как sed работает на уровне строк, а не на уровне слов. Одним из решений может быть простая трубка к большему количеству sed:[
] [sed -n '/%packages/,/%end/ w file2' file1 | sed -e '1d' -e '$d'
]
[]-e[], которая вводит следующие новые возможности:[
]
[]-e[
] позволяет выполнять несколько команд на одном и том же входе[
]
[]1[
] показывает, что нумерация строк, работающая[
]
[]d[
], предназначена для удаления паттерна соответствия - строка номер 1 в первой команде[
]
[]$[
] является концом входного потока. Так как на уровне строки, а не на уровне слова, действует sed, то удаляется вся строка в конце[
]Но, на самом деле, мы можем сделать это в одном вызове sed, используя фигурные скобки для группировки (здесь, в скрипте для наглядности):[
] [#!/bin/bash
sed -n '
/%packages/,/%end/ {
/%packages/n
/%end/ !{
w file2
}
}
' file1
]
[]Единственное, что здесь нового (кроме группировки) - это использование []! [
] для отрицания совпадения.[
]
[]/узор/n[
] Подавите линию печати шаблоном (так же, как []-n[
] в начале).
[]/образец/ ![
] Выбирает все, что НЕ совпадает с образцом (обратное совпадение).
Причина, BTW, довольно проста. Если бы мы сделали еще один []/%end/n[
] для подавления шаблона %end, мы бы также подавили его от ограничения нашего диапазона, и файл был бы распечатан до конца.[