с учетом ваших данных и вашего разреженного описания (это всегда хорошо, чтобы показать результат, который вам нужен / ожидаемый И и любые сообщения об ошибках, которые вы получаете), попробуйте это
cat myData
foo;3
bar;1
cat myFixer.sh
#!/bin/bash
awk '
BEGIN {FS=";" ; OFS=";"}
{
if ($1 == target ) {
$2 += incr
targFound=1
}
print $0
}
END {
if (! ( targFound) ) {
print target OFS "0"
}
}' target="foo" incr=3 myData
# output
foo;6
bar;1
foo;3
bar;1
BAD;0
Я использую incr=3
, чтобы показать, что это общее решение.Если вам нужно увеличение +1
, просто измените аргумент на incr=1
.
Некоторые awks хотят видеть переменные командной строки, установленные как -v target=foo -v incr=3
.
Вы можете легко изменитьэтот bash-скрипт, принимающий аргументы для target и incr, входной файл в виде $ 1 $ 2 $ 3.
Прямо сейчас вывод просто появляется на вашем экране.Я бы порекомендовал перенаправить вывод в новый файл.
myFixer.sh > myData.New
Обратите внимание, что FS - это специальная переменная awk, что означает FieldSeparator.OFS - это OutputFieldSeparator, поэтому в вашем случае можно легко преобразовать в истинный CSV, изменив OFS на OFS = ","
Awk анализирует каждую строку ввода в полях;вся строка называется $ 0, в то время как каждому элементу, разделенному с помощью FS (в вашем случае ';'), присваивается последовательный номер, перемещающийся слева направо, поэтому первое поле называется $ 1, второе - $ 2 и т. д.Awk имеет много других внутренних переменных, включая NF (Number_of_Fields), который устанавливается для каждой строки считываемых данных.Вы можете использовать NF отдельно для проверки правильности количества полей в строке (для одного примера) или вы можете «разыменовать» значение NF с помощью символа «$» и иметь доступ к последнему значению в каждой строке с помощью'$ NF.Для вашего примера, мы могли бы переписать $ 2 как $ NF.
Действие по умолчанию для awk, заданного кода в блоках {..}, состоит в том, чтобы прочитать каждую строку ввода и затем обработать ее в соответствии с логикой внутри блока.В вашем случае, мы смотрим на поле один, чтобы увидеть, является ли это целевой строкой, и если это так, мы увеличиваем значение там.
Для всех записей мы выводим полную строку, независимо от того, была ли онаувеличивается или нет.
Блок кода BEGIN выполняется перед чтением любых записей из входных файлов и является способом инициализации переменных (или в этом случае вы переопределяете значение по умолчанию FS).
Блок END выполняется после прочтения всех входных файлов.Поскольку вам нужно вывести foo; 0, если его там нет, мы сохраняем флаг, чтобы указать, была ли найдена ваша цель поиска или нет.Последнее, что мы делаем, это проверяем, была ли цель найдена, и если нет, выдают строку с 'target OFS 0' в качестве текста.
Надеюсь, это поможет.
PS
Добро пожаловать в StackOverflow, пожалуйста, позвольте мне напомнить вам о трех вещах, которые мы обычно делаем здесь: 1) Получая помощь, постарайтесь также помочь ей, отвечая на вопросы в вашей области знаний 2) Читайте часто задаваемые вопросы, http://tinyurl.com/2vycnvr, 3) Когда вы видите хорошие вопросы и ответы, оцените их, используя серые треугольники, http://i.imgur.com/kygEP.png, поскольку доверие к системе основано на репутации, которую пользователи получают, делясь своими знаниями.Также не забудьте принять ответ, который лучше решит вашу проблему, если таковой имеется, нажав на значок галочки, http://i.imgur.com/uqJeW.png