
У меня есть куча CSV-файлов с похожим содержанием. Значения обычно разделены запятыми и выглядят так.
product_a, domestic, 500
product_a, abroad, 15
product_b, domestic, 313
product_b, abroad, 35
product_c, domestic, 411
product_c, abroad, 84
product_d, domestic, 25
product_d, abroad, 2
...
То, чего я пытаюсь добиться с помощью AWK (потому что я считаю, что SED не является подходящим инструментом для таких операций, но я относительно новый пользователь Linux...) — это сумма каждого произведения (столбец 1), вставленная как столбец номер 2. Я могу сделать что-то вроде этого
awk -F, '{a[$1]+=$3;}END{for (i in a)print i", "a[i];}' filename
чтобы получить эти значения (суммы)
product_a, 515
product_b, 348
product_c, 495
product_d, 27
...
но я все еще не имею ни малейшего представления, как вставить их в качестве второго столбца в исходный файл, в такой форме:
product_a, 515, domestic, 500
product_a, 515, abroad, 15
product_b, 348, domestic, 313
product_b, 348, abroad, 35
product_c, 495, domestic, 411
product_c, 495, abroad, 84
product_d, 27, domestic, 25
product_d, 27, abroad, 2
...
В последнее время я немного использую sed и awk, но мои попытки обычно приводят к ошибке (например, попытка использовать скалярное значение как массив).
Порядок строк меня не волнует, но я предполагаю, что смогу использовать ответ в качестве команды пакетного файла.
$ for f in *.csv; do
That Shiny Enigmatic Command > tmp && mv tmp $f
done
РЕДАКТИРОВАТЬ
Спасибо @KM. Я достиг того места, где я могу делать то, что хочу, за 3 шага.
1 шаг:
$ for f in *.csv; do
awk -F, '{a[$1]+=$3;}END{for (i in a)print i", "a[i];}' $f | sort > sum$f
done
2-й шаг:
$ for f in [^sum]*.csv; do
join -t ',' $f sum$f | awk -F, '{print $1"," $4"," $2"," $3}' > tmp && mv tmp $f;
done
В конечном итоге просто rm sum*.*
. Есть ли способ выполнить это как одну команду из терминала? Или вне его?
решение1
Сохраните сумму в файле с именем sum
, отсортированном
awk -F, '{a[$1]+=$3;}END{for (i in a)print i", "a[i];}' filename | sort > sum
cat sum
product_a, 515
product_b, 348
product_c, 495
product_d, 27
Объедините два файла, первый столбец первого файла с первым столбцом второго (представьте себе «ключи»); передайте их по конвейеру awk
и выведите переупорядоченные столбцы, используя ,
в качестве разделителя полей ( -F
)икак разделитель выходных полей ( -OFS
)
join -t ',' -1 1 -2 1 filename sum | awk -F, -OFS=, {'print $1,$4,$2,$3}'
product_a, 515, domestic, 500
product_a, 515, abroad, 15
product_b, 348, domestic, 313
product_b, 348, abroad, 35
product_c, 495, domestic, 411
product_c, 495, abroad, 84
product_d, 27, domestic, 25
product_d, 27, abroad, 2