Извините, принятый ответ - плохая информация по нескольким фронтам.
/proc/sys/kernel/pid_max не имеет ничего общего с максимальным количеством процессов, которые могут быть запущены в любой момент времени. Это, по сути, максимальный числовой идентификатор процесса, который может быть присвоен ядром.
В ядре Linux процесс и поток — это одно и то же. Они обрабатываются таким же образом ядром. Они оба занимают место в task_struct структуре данных. Поток, по общепринятой терминологии, в Linux — это процесс, который совместно использует ресурсы с другим процессом (они также будут совместно использовать идентификатор группы потоков). Поток в ядре Linux в значительной степени является концептуальной конструкцией для планировщика.
Теперь, когда вы понимаете, что ядро в значительной степени не различает поток и процесс, должно иметь больше смысла, что /proc/sys/kernel/threads-max на самом деле является максимальным количеством элементов, содержащихся в структуре данных task_struct. Это структура данных, содержащая список процессов или, как их можно назвать, задач.
ulimit — это, как следует из названия, ограничение на пользователя. Флаг -u определяется как «Максимальное количество процессов, доступных одному пользователю». Элемент task_struct содержит идентификатор uID пользователя, создавшего задачу. A пер-Счетчик uid поддерживается и увеличивается/уме умещается каждый раз, когда задача добавляется/удаляется из task_struct. Таким образом, ulimit -u указывает на максимальное количество элементов (процессов), которые один конкретный пользователь может иметь в пределах task_struct в любой момент времени.
Я надеюсь, что это прояснит ситуацию.
Решение, которое я создал, не очень короткое, но достаточно простое, чтобы его можно было легко читать. если ваша задача не состояла в том, чтобы сделать все это с помощью sed ...?
#!/usr/bin/bash
cp A.txt D.txt
x=1
length=$(wc -l B.txt | sed 's/\ .*//g')
until [ $x -eq $length ]; do
Bx=$(awk "NR==$x" B.txt)
Cx=$(awk "NR==$x" C.txt)
sed -i "s/$Bx/$Cx/g" D.txt
x=$(($x+1))
done
rm -f ./sed*
обратите внимание, что этот сценарий создает тонну ненужных файлов, если B.txt длиннее C.txt и, возможно, наоборот (не тестировал это так далеко)
В простом примере, который вы показываете, когда каждое из целевых слов появляется в файле только один раз, вы можете просто сделать:
$ paste fileB fileC | while read a b; do sed -i "s/$a/$b/" fileA; done
$ cat fileA
Hello John, how is your wife? where is grandpa?
Команда paste
распечатает данные из обоих файлов вместе:
$ paste fileB fileC
Peter John
dad wife
mom grandpa
Мы передаем это через простой цикл при чтении
, который будет перебирать каждую строку, сохраняя значение из fileB
как $ a
и значение из fileC
как $ b
. Затем команда sed
заменит первое вхождение $ a
на $ b
. Это повторяется трижды.
Этот подход хорош, если вы знаете, что ваши целевые слова появляются в файле только один раз (они должны быть, иначе вам нужно будет предоставить более подробную информацию, которую мы можем использовать, чтобы определить, какое вхождение следует заменить), и если ваш файлы крошечные, как то, что вы показали. Для больших файлов это займет много времени и очень неэффективно, так как его нужно будет запускать один раз для каждой пары слов.
Итак, если у вас есть файлы большего размера, вам может потребоваться что-то вроде этого:
paste fileB fileC |
perl -lane '$words{$F[0]}=$F[1]}
END{open(A,"fileA"); while(<A>){s/$_/$words{$_}/ for keys %words; print}'
Самый простой способ сделать это с помощью sed
- обработать эти два списка и превратить их в файл сценария , например
s/line1-from-fileB/line1-from-fileC/g
s/line2-from-fileB/line2-from-fileC/g
....................................
s/lineN-from-fileB/lineN-from-fileC/g
, который затем выполнит sed
, редактируя fileA
. Правильный способ - сначала обработать LHS
/ RHS
и исключить любые специальные символы, которые могут появиться в этих строках, а затем присоединиться к LHS
] и RHS
, добавляя s
, разделители /
и g
(например, с пастой
) и результат для sed
:
paste -ds///g /dev/null /dev/null \
<(sed 's|[[\.*^$/]|\\&|g' fileB) <(sed 's|[\&/]|\\&|g' fileC) \
/dev/null /dev/null | sed -f - fileA
Итак, вот оно: одна paste
и три sed
, которые будут обрабатывать каждый файл только один раз, независимо от количества линий.
Предполагается, что ваша оболочка поддерживает подстановку процессов и что ваш sed
может читать файл сценария из stdin . Кроме того, он не редактируется на месте (я пропустил переключатель -i
, поскольку он не поддерживается всеми sed
s)
Это может помочь решить вашу проблему. (См .: https://unix.stackexchange.com/questions/283017/awk-command-i-want-to-compare-two-rows -in-two-files-and-update-the-second-file-i )
Source.txt имеет следующие две строки:
OldString
NewString
Перед выполнением команды Target.txt содержит следующие строки:
OldString ==> NewString
This is Target File containing OldString now.
OldString is to be replaced.
NewString won't get impacted.
Use :
awk -v lookupStr=`awk 'NR==1' Source.txt` -v replacementStr=`awk 'NR==2' Source.txt` 'NR==2 && (idx=index($0,lookupStr)) { $0=substr($0,1,idx-1) replacementStr substr($0,idx+length(lookupStr)) } 1' Target.txt > temp.txt && mv temp.txt Target.txt
Выполнение команды после выполнения Target.txt имеет следующую строку:
OldString ==> NewString
This is Target File containing NewString now.
OldString is to be replaced.
NewString won't get impacted.
Здесь я определил две переменные lookupStr и replaceStr. обе присвоены строке №1 и строке №2 Source.txt соответственно. Затем в строке Sencond файла Target.txt я заменяю содержимое $ 0 первым символом до индекса lookupStr (т.е. "OldString") затем добавление replaceStr (т.е. «NewString») и затем конкатенация остальных символов. В конце вывод записывается в temp.txt, и он переименовывается в Target.txt
. Если вам нужно выполнить это упражнение по замене всего файла, просто удалите условие NR == 2 && из приведенной выше команды.
Если вы хотите, чтобы замены производились независимо друг от друга, например, для:
foo -> bar
bar -> foo
Подано на
foobar
В результате:
barfoo
в отличие от foofoo
как сделал бы наивный s/foo/bar/g; s/bar/foo/g
перевод, вы могли бы сделать:
perl -pe '
BEGIN{
open STRINGS, "<", shift@ARGV or die"STRINGS: $!";
open REPLACEMENTS, "<", shift@ARGV or die "REPLACEMENTS: $!";
while (defined($a=<STRINGS>) and defined($b=<REPLACEMENTS>)) {
chomp ($a, $b);
push @repl, $b;
push @re, "$a(?{\$repl=\$repl[". $i++. "]})"
}
eval q($re = qr{). join("|", @re). "}";
}
s/$re/$repl/g' strings.txt replacements.txt fileA
В patterns.txt
ожидается perl
регулярных выражений. Поскольку регулярные выражения Perl могут выполнять произвольный код, важно, чтобы они были очищены. Если вы хотите заменить только фиксированные строки, вы можете изменить это на:
perl -pe '
BEGIN{
open PATTERNS, "<", shift@ARGV or die"PATTERNS: $!";
open REPLACEMENTS, "<", shift@ARGV or die "REPLACEMENTS: $!";
for ($i = 0; defined($a=<PATTERNS>) and defined($b=<REPLACEMENTS>); $i++) {
chomp ($a, $b);
push @string, $a;
push @repl, $b;
push @re, "\\Q\$string[$i]\\E(?{\$repl=\$repl[$i]})"
}
eval q($re = qr{). join("|", @re). "}";
}
s/$re/$repl/g' patterns.txt replacements.txt fileA