Мне нужно объединить файл конфигурации 1 с файлом конфигурации 2. Если в файле 1 есть файл 2, добавьте его в конец файла 2. Я могу заменить печать на систему для исправления ошибки, но я не знаю, почему печать не работает.
Используйте print i" = " a[i] >> ARGV[2];
, не удалось добавить текст в конец текста
1.txt,Обратите внимание, что 3-я строка пустая:
key=5678
abc=000
key=1234
test.awk:
#!/usr/bin/env -S gawk -F= -f
{
key = gensub(/\s/, "", "g", $1);
if (NR==FNR) {
a[key]=$2;
} else {
b[key]=$2;
}
}
END{
for (i in a) {
if (b[i] == "") {
print "bi = empty, append to end of file:" i" = "a[i];
print i" = "a[i] >> ARGV[2];
# system("echo " i " = " a[i] ">>" ARGV[2]);
} else if (a[i] != b[i]) {
cmd = sprintf("sed -i -r 's@\\s*(%s)\\s*=.*@\\1=%s@' %s", i, a[i], ARGV[2]);
system(cmd);
}
}
}
запустить ./test.awk 1.txt 2.txt результат :
$ ./test.awk 1.txt 2.txt
bi = empty, append to end of file:=
bi = empty, append to end of file:abc=000
$ cat 2.txt
key=5678
=
Почему abc=000 не добавляется в 2.txt? Если он изменен на system ("echo" I "=" a [i] ">" argv [2]), и снова все в порядке, есть ли ошибка в печати?
В руководстве gnu awk «5.9 Закрытие перенаправления ввода и вывода» требуется функция закрытия вызова, когда несколько команд работают с одним и тем же файлом, например, pipe или cmd, это очень плохо, поэтому я отказываюсь от печати >>, использую только system().
Наконец, я использую этот скрипт:
#!/usr/bin/env -S gawk -F"=|is" -f
# File: sync_kernelconfig.awk
# Author: Edward.Tang
# Mail: [email protected]
# Function: 同步文件1的内核配置到文件2
function set_value(array, comment, k, v)
{
if (!/^\s*#/) {
array[k]=v;
} else {
comment[k]=$2;
}
}
{
key = gensub(/#|\s/, "", "g", $1);
if (key == "") next; # 跳过空行
if (NR==FNR) {
set_value(a1, c1, key, $2);
} else {
set_value(a2, c2, key, $2);
line[key] = $0; # line data of file2
}
}
END {
for (i in a1) {
if (a2[i] == "") {
if (c2[i] == "") {
system("echo " i " = " a1[i] ">>" ARGV[2]);
} else {
cmd = sprintf("sed -i -r 's~%s~%s=%s~' %s", line[i], i, a1[i], ARGV[2]);
system(cmd);
}
} else if (a1[i] != a2[i]) {
cmd = sprintf("sed -i -r 's~%s~%s=%s~' %s", line[i], i, a1[i], ARGV[2]);
system(cmd);
}
}
for (i in c1) {
if (a2[i] != "") {
cmd = sprintf("sed -i -r 's~%s~# %s is%s~' %s", line[i], i, c1[i], ARGV[2]);
system(cmd);
}
}
}
Также было бы неплохо добавить логику вашей программы вместе с образцом ввода и ожидаемым результатом в ваш вопрос для лучшего понимания.
Попробуйте изменить блок END на блок ENDFILE
@RamanSailopal После использования ENDFILE результатом будет key=5678 = key=5678 abc=000 =
В руководстве gnu awk «5.9 Закрытие перенаправлений ввода и вывода» требуется функция закрытия вызова, когда несколько команд работают с одним и тем же файлом, например, pipe или cmd, это очень плохо.
Поэтому мне нужно использовать:
print i" = "a[i] >> ARGV[2];
close(ARGV[2]);
или:
system("echo " i " = " a1[i] ">>" ARGV[2]);
Обратите внимание, что версия system()
медленнее и крайне небезопасна — если ваши данные имеют $(somecommand)
, ваша оболочка будет запускать это как код. И вы не можете просто исправить это, добавив больше кавычек, потому что им можно противопоставить кавычки в данных.
@CharlesDuffy Да, поэтому я сейчас рассматриваю возможность использования perl. Кажется, что мгновенное редактирование с помощью awk невозможно.
Гораздо лучше было бы реструктурировать вашу программу так, чтобы она не состояла из редактирования на месте. Каждое такое редактирование перезаписывает весь ваш файл; это глубоко неэффективно.
@CharlesDuffy Вы имеете в виду, что записываете все элементы, а затем записываете один раз в файл? У меня нет лучшей идеи.
What does 注意第三行是个空行 mean? Can you translate it, please