Как вставить содержание файла в другой файл перед шаблоном (маркер)?

Во-первых, простой способ: rsync имеет a --bwlimit параметр. Это - постоянный уровень, но можно использовать это для легкого снижения скорости его.

Теперь, если Вы хотите адаптивный уровень, существует платформа управления трафиком Linux, которая является на самом деле справедливо сложной. Существует несколько ссылок, о которых я знаю:

Лично, когда я должен настроить это, я использую tcng для упрощения задачи. Вот пример:

dev office {
    egress {
        class ( <$ssh> ) 
            if ip_tos_delay == 1 && tcp_sport == PORT_SSH ;
        class ( <$kyon> )
            if ip_dst == 172.16.1.62; // monitoring host
        class ( <$fast> )
            if ip_tos_delay == 1;
        class ( <$default> )
            if 1;

        htb() {
            class ( rate 1440kbps, ceil 1440kbps ) {
                $ssh = class ( rate 720kbps, ceil 1440kbps ) { sfq; };
                $kyon = class ( rate 360kbps, ceil 1440kbps ) { sfq; };
                $fast = class ( rate 180kbps, ceil 1440kbps ) { sfq; };
                $default = class ( rate 180kbps, ceil 1440kbps ) { sfq; };
            }
        }
    }
}

В том примере трафик, отсылаемый по офисному интерфейсу, классифицируется в несколько классов: ssh, kyon, быстро, и значение по умолчанию. Ссылка (T1, когда это использовалось) ограничивается на уровне 1440 Кбит/с (это должно быть немного ниже, чем фактическая скорость канала, так, чтобы буферизация произошла на поле Linux, не маршрутизаторе). Вы видите, что ssh присваивают 720 Кбит/с, kyon 360, и т.д. Все могут разорвать к полному тарифу (перекрытие). Когда существует конкуренция, действия 'уровня' как отношение, таким образом, ssh дали бы 1/2, kyon 1/4, и т.д. 'sfq' говорит, как обработать несколько ssh сессий; sfq является формой циклического алгоритма.

35
10.03.2018, 00:43
10 ответов

sed имеет функцию для этого и может сделать встроенную модификацию:

sed -i -e '/Pointer/r file1' file2

Но это помещает Вашу строку Указателя выше file1. Для помещения его ниже задержите вывод строки:

sed -n -i -e '/Pointer/r file1' -e 1x -e '2,${x;p}' -e '${x;p}' file2 
35
27.01.2020, 19:36
  • 1
    Мог Вы объяснять что -e 1x -e '2,${x;p}' -e '${x;p}' ? Я понимаю, что Вы обмениваетесь материалом в буфере шаблона и затем печатаете его, но я не знаю, какой ни почему Вы добавили тихую опцию -n вначале. –  hdl 24.09.2015, 17:47

Без использования sed или awk...

Во-первых, найдите Ваш строкой, на которой Ваш шаблон:

line=$(grep -n 'Pointer' file2 | cut -d ":" -f 1)

Затем используйте 3 команды для вывода требуемого результата:

{ head -n $(($line-1)) file2; cat file1; tail -n +$line file2; } > new_file

Это имеет недостаток доступа 3 раза к файлу file2, но могло бы быть более ясным, чем a sed из awk решение.

18
27.01.2020, 19:36

awk делает это довольно легким.
Вставьте строку перед файлом:

awk '/Pointer/{while(getline line<"innerfile"){print line}} //' outerfile >tmp
mv tmp outerfile

Сделать внутреннюю печать файла после Pointer строка, просто переключите порядок шаблонов (необходимо добавить точку с запятой для получения действия по умолчанию), и можно отбросить line переменная:

awk '//; /Pointer/{while(getline<"innerfile"){print}}' outerfile >tmp
mv tmp outerfile

И просто потому что никто не использовал perl все же,

# insert file before line
perl -e 'while(<>){if($_=~/Pointer/){system("cat innerfile")};print}' outerfile

# after line
perl -e 'while(<>){print;if($_=~/Pointer/){system("cat innerfile")}}' outerfile
10
27.01.2020, 19:36
  • 1
    его работа, но то, что это было удаленным строки, содержащей указатель –  user1228191 28.02.2012, 20:18
  • 2
    аналогично, как Вставить содержание файла 1 в файле 2 после того "Указателя", содержащего строку с помощью awk –  user1228191 28.02.2012, 20:21
  • 3
    @user1228191 Зафиксировал первое, добавило второе. –  Kevin 28.02.2012, 20:42
  • 4
    'perl' версия, кажется, не работает. system("cat innerfile") производит innerfile к консоли. Я пропускаю что-то? –  kaartic 09.07.2017, 13:30
  • 5
    awk [таращит глаза '/<тело> / {в то время как (getline строка <" $HOME/bin/SrunScenario.style") {печатают строку}}//' index.html> new_index.html] просто циклы и печать миллионы строк. таращите глаза V4.2.0, Что я пропускаю здесь? –  JESii 14.02.2018, 01:15

Используйте цикл для чтения строк в file2. Если Вы находите строку, запускающуюся с Pointer, затем распечатайте file1. Это показывают ниже:

#!/bin/bash
while IFS= read -r line
do
    if [[ "$line" =~ ^Pointer.*$ ]]
    then
        cat file1
    fi
    echo "$line"
done < file2
6
27.01.2020, 19:36

Простая задача для ed :

ed -s file1 <<IN
/Pointer/-r file2
,p
q
IN

-r file1 считывает указанный файл после адресной строки, которая в данном случае является строкой, предшествующей первой строке, соответствующей указателю . Таким образом, содержимое file2 будет вставлено только один раз, даже если Указатель встречается в нескольких строках.Если вы хотите вставить его перед каждой совпадающей строкой, добавьте лобальный флаг g :

ed -s file1 <<IN
g/Pointer/-r file2
,p
q
IN

Замените , p на w , если вы хотите отредактировать файл в- место.


Принятый ответ sed работает в большинстве случаев, но если маркер находится в последней строке, команда не будет работать должным образом: она вставит содержимое File1 после маркера.
Сначала я пробовал использовать:

sed '/Pointer/{r file1
N}' file2

, который также отлично работает (поскольку r сделает свое волшебство в конце цикла), но имеет ту же проблему, если маркер в последней строке (после последней строки нет строки N ext). Чтобы обойти это, вы можете добавить новую строку к своему вводу:

sed '/Pointer/{              # like the first one, but this time even if the
r file1                      # marker is on the last line in File2 it
N                            # will be on the second to last line in
}                            # the combined input so N will always work;
${                           # on the last line of input: if the line is
/^$/!{                       # not empty, it means the marker was on the last
s/\n$//                      # line in File2 so the final empty line in the
}                            # input was pulled i\n: remove the latter;
//d                          # if the line is empty, delete it
}' file2 <(printf %s\\n)

Это вставит содержимое file2 перед каждой совпадающей строкой. Чтобы вставить его только перед первой совпадающей строкой, вы можете использовать команду l и просто тянуть строку n ext, пока не дойдете до конца файла:

sed '/Pointer/{
r file2
N
:l
$!n
$!bl
}
${
/^$/!{
s/\n$//
}
//d
}' file1 <(printf %s\\n)

С этими ] sed решения, вы теряете возможность редактировать на месте (но можете перенаправить в другой файл).

7
27.01.2020, 19:36

Это довольно просто с AWK:

File1 в File2 перед шаблоном = "Pointer"

Сначала загрузите содержимое File1 в переменную

f1="$(<File1)"

, затем выполните вставку

awk -vf1="$f1" '/Pointer/{print f1;print;next}1' file2

(Или, если вы хотите вставить File1 после "Pointer")

awk -vf1="$f1" '/Pointer/{print;print f1;next}1' file2
2
27.01.2020, 19:36

Есть несколько способов сделать это с помощью sed. Один из способов - отложенное чтение, как рекомендуется в принятом ответе. Это также можно записать как:

sed -e '$!N;P;/\nPointer/r file1' -e D file2

... с небольшим явным просмотром вперед вместо просмотра назад, реализованного в другом месте с буфером удержания. Однако в этом случае неизбежно возникнет та же проблема с последней строкой, которую отмечает @don_crissti, поскольку N does инкрементирует цикл строки, а команда read применяется по номеру строки.

Это можно обойти:

echo | sed -e '$d;N;P;/\nPointer/r file1' -e D file2 -

Не все sedы будут интерпретировать - как стандартный ввод, но многие это делают. (POSIX говорит sed должен поддерживать - как стандартный ввод, если исполнитель хочет, чтобы - означали стандартный ввод???)

Другой способ - обрабатывать добавляемое содержимое по порядку. Есть еще одна команда, которая schedules выводит так же, как read, а sed применит ее и read в том порядке, в котором они прописаны в сценарии. Однако это немного сложнее - это подразумевает использование одного sed для append Pointer совпадения с выводом другого sed в своем сценарии.

sed '   /Pointer/!d                  #only operate on first match
        s/[]^$&\./*[]/\\&/g;H        #escape all metachars, Hold
        s|.*|/&/!p;//!d|p;g          #print commands, exchange
        s|.|r file1&a\\&|;q' file2|  #more commands, quit
        sed -nf - file2              #same input file

То есть, по сути, первый sed пишет второму sed скрипт, который второй sed читает на стандартном входе (возможно...) и применяет по очереди. Первый sed работает только при первом найденном совпадении для Pointer, после чего quits input. Его задача состоит в том, чтобы...

  1. s/[]^$&\./*[]/\\\&/g;H
    • Убедитесь, что все символы шаблона надежно зашифрованы обратным слешем, потому что второй sed должен будет интерпретировать каждый прочитанный бит буквально, чтобы все было правильно. Как только это будет сделано, поместите копию в Hold space.
  2. s|.*|/&/!p;//!d|p; x
    • Скажите второму sed, чтобы print каждую строку ввода ! кроме той /&/, которую мы только что проверили по шаблону; а затем delete all of the same. print команды на втором sed, затем exchange hold и pattern buffers для работы с нашей сохраненной копией.
  3. s|.|r file1&a\\\\&|p;q
    • Единственный символ, с которым мы здесь работаем, это \newline, потому что sed добавит его, когда мы Held строку до этого. Поэтому мы вставляем команду r file1, за ней следует \newline, затем команда a\\\ для append, за которой также следует \newline. Вся остальная часть нашей строки Held следует за этой последней \newline.

Скрипт, который пишет первый, выглядит примерно так:

/Pointer-file2   "23"/!p;//!d
r file1
a\
Pointer-file2   "23"

В основном второй sed будет печатать все строки, кроме той, которую первый sed установил на append. Для этой конкретной строки две отложенные записи в standard-out будут запланированы - первая будет rначалом file1, а вторая - копией строки, которую мы хотим получить после неё. Первый sed в данном случае даже не нужен (видите? без обратных слешей), но важно безопасно экранировать так, как я это делаю здесь, всякий раз, когда совпадение шаблонов используется в качестве входных данных.

В любом случае... есть несколько способов.

4
27.01.2020, 19:36

мой предпочтительный способ: создание шаблонов .

sed 's/CHANGEME/$x/g' origfile | x="$(<file2insert)" envsubst '$x' > newfile

Это заменит каждое CHANGEME в origfile содержимым file2insert . Удалить последний g из sed, чтобы заменить только первое вхождение CHANGEME .

2
27.01.2020, 19:36
 awk '/Pointer/{system("cat File1")}1' File2
1
27.01.2020, 19:36
sed '2r fil1' fil2

выход

line1-file2     "25"  
line2-file2     "24"  
line1-file1      "1" 
line2-file1      "2"
line3-file1      "3" 
line4-file1      "4" 
Pointer-file2   "23"  
line4-file2     "22" 
line5-file2     "21"
-1
15.10.2021, 12:53

Теги

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