Во-первых, простой способ: 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 является формой циклического алгоритма.
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
Без использования 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
решение.
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
system("cat innerfile")
производит innerfile
к консоли. Я пропускаю что-то?
– kaartic
09.07.2017, 13:30
Используйте цикл для чтения строк в file2. Если Вы находите строку, запускающуюся с Pointer
, затем распечатайте file1. Это показывают ниже:
#!/bin/bash
while IFS= read -r line
do
if [[ "$line" =~ ^Pointer.*$ ]]
then
cat file1
fi
echo "$line"
done < file2
Простая задача для 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
решения, вы теряете возможность редактировать на месте (но можете перенаправить в другой файл).
Это довольно просто с 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
Есть несколько способов сделать это с помощью sed
. Один из способов - отложенное чтение, как рекомендуется в принятом ответе. Это также можно записать как:
sed -e '$!N;P;/\nPointer/r file1' -e D file2
... с небольшим явным просмотром вперед вместо просмотра назад, реализованного в другом месте с буфером удержания. Однако в этом случае неизбежно возникнет та же проблема с последней строкой, которую отмечает @don_crissti, поскольку N
does инкрементирует цикл строки, а команда r
ead применяется по номеру строки.
Это можно обойти:
echo | sed -e '$d;N;P;/\nPointer/r file1' -e D file2 -
Не все sed
ы будут интерпретировать -
как стандартный ввод, но многие это делают. (POSIX говорит sed
должен поддерживать -
как стандартный ввод, если исполнитель хочет, чтобы -
означали стандартный ввод???)
Другой способ - обрабатывать добавляемое содержимое по порядку. Есть еще одна команда, которая schedules выводит так же, как r
ead, а sed
применит ее и r
ead в том порядке, в котором они прописаны в сценарии. Однако это немного сложнее - это подразумевает использование одного sed
для a
ppend 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
, после чего q
uits input. Его задача состоит в том, чтобы...
s/[]^$&\./*[]/\\\&/g;H
sed
должен будет интерпретировать каждый прочитанный бит буквально, чтобы все было правильно. Как только это будет сделано, поместите копию в H
old space. s|.*|/&/!p;//!d|p; x
sed
, чтобы p
rint каждую строку ввода !
кроме той /&/
, которую мы только что проверили по шаблону; а затем d
elete all of the same. p
rint команды на втором sed
, затем ex
change h
old и pattern buffers для работы с нашей сохраненной копией. s|.|r file1&a\\\\&|p;q
\n
ewline, потому что sed
добавит его, когда мы H
eld строку до этого. Поэтому мы вставляем команду r file1
, за ней следует \n
ewline, затем команда a\\\
для a
ppend, за которой также следует \n
ewline. Вся остальная часть нашей строки H
eld следует за этой последней \n
ewline. Скрипт, который пишет первый, выглядит примерно так:
/Pointer-file2 "23"/!p;//!d
r file1
a\
Pointer-file2 "23"
В основном второй sed
будет печатать все строки, кроме той, которую первый sed
установил на a
ppend. Для этой конкретной строки две отложенные записи в standard-out будут запланированы - первая будет r
началом file1
, а вторая - копией строки, которую мы хотим получить после неё. Первый sed
в данном случае даже не нужен (видите? без обратных слешей), но важно безопасно экранировать так, как я это делаю здесь, всякий раз, когда совпадение шаблонов используется в качестве входных данных.
В любом случае... есть несколько способов.
мой предпочтительный способ: создание шаблонов .
sed 's/CHANGEME/$x/g' origfile | x="$(<file2insert)" envsubst '$x' > newfile
Это заменит каждое CHANGEME в origfile содержимым file2insert . Удалить последний g из sed, чтобы заменить только первое вхождение CHANGEME .
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"
-e 1x -e '2,${x;p}' -e '${x;p}'
? Я понимаю, что Вы обмениваетесь материалом в буфере шаблона и затем печатаете его, но я не знаю, какой ни почему Вы добавили тихую опцию-n
вначале. – hdl 24.09.2015, 17:47