LINUX.ORG.RU

Скрипт (аналог Excel (ВПР) с использованием awk и sed)

 , ,


0

1

Не могу победить скрипт, прошу помощи.

Есть файл input.csv - 32 столбца, разделитель ","


Столбец1,...,Столбец3,...,Столбец10,Столбец11,...,Столбец15,...,Столбец32
10000,...,AAA000011,...,0,5,...,0,...,111
10001,...,AAA000012,...,0,5,...,0,...,111
10002,...,AAA000013,...,0,5,...,0,...,111
...
22222,...,AAA033333,...,0,5,...,0,...,111

Также есть файл price.csv - 3 столбца, разделитель ","


AAA000011,12,728
AAA000013,18,935
AAA000015,2,1024
...
AAA022222,22,426

На выходе требуется получить файл output.csv идентичный input.csv, в котором при наличии в файле price.csv позиции (столбец 3 и 1 соответственно) значение столбца 10 меняется на значение столбца 2 price.csv умноженное на 1,2, столбца 11 - с 5 на 7, столбца 15 - на значение столбца 3 price.csv.
Поиском по интернетам нашел только конструкцию:

# !/bin/bash
FILE='price.csv'
FILE2='input.csv'

while read LINE
do
     ip=`echo $LINE | awk -F "," '{print $1}'`
     if grep -q $ip $FILE2
     then grep $ip $FILE2 | awk -F "," '{print $3}'
     echo $LINE
fi
done  < $FILE
Реализовать ее вывод в файл не смог. Куда перенаправление вывода не вставлю, то одно значение из price.csv выводит, то одну строчку из input.csv, то ничего. А замену в исходном файле значений реализовать вообще не смог. Понимаю, что нужно это делать sed'ом, но как...
Прошу помочь.



Последнее исправление: Neuro75 (всего исправлений: 2)

и обязательно на sh?

в котором при наличии в файле price.csv позиции

если это грепом делать - будет медленно работать. (проверка за O(n) ).

Или файлы маленькие?

Tanger ★★★★★
()

А можно на примере, а то непонятно описана хотелка.

Niroday
()
Ответ на: комментарий от Tanger

Или файлы маленькие?

Файлы небольшие - input.csv - 15000 строк, price.csv - 1000 строк.

А можно на примере, а то непонятно описана хотелка.

Кусок input.csv:

product_id,model,sku,upc,ean,jan,isbn,mpn,location,quantity,stock_status_id,image,manufacturer_id,shipping,price,points,tax_class_id,date_available,weight,weight_class_id,length,width,height,length_class_id,subtract,minimum,sort_order,status,viewed,noindex,date_added,date_modified
10000,AAA14223,AA-A-14223,,,,,,,0,5,catalog/4U/none.jpg,11,1,0.0000,0,0,2017-09-17,0.00000000,0,0.00000000,0.00000000,0.00000000,0,1,1,1,1,0,1,2017-09-17 17:31:04,2017-09-17 17:31:04
10001,AAA20088,AA-A-20088,,,,,,,0,5,catalog/4U/none.jpg,11,1,0.0000,0,0,2017-09-17,0.00000000,0,0.00000000,0.00000000,0.00000000,0,1,1,2,1,0,1,2017-09-17 17:31:04,2017-09-17 17:31:04
10002,AAA28049,AA-A-28049,,,,,,,0,5,catalog/4U/none.jpg,11,1,0.0000,0,0,2017-09-17,0.00000000,0,0.00000000,0.00000000,0.00000000,0,1,1,3,1,0,1,2017-09-17 17:31:04,2017-09-17 17:31:04
10003,AAA57687,AA-A-57687,,,,,,,0,5,catalog/4U/none.jpg,11,1,0.0000,0,0,2017-09-17,0.00000000,0,0.00000000,0.00000000,0.00000000,0,1,1,4,1,0,1,2017-09-17 17:31:04,2017-09-17 17:31:04

Кусок price.csv:

AA-A-14223,5,534
AB-A-00102,6,288
AB-B-00103,1,479
AB-B-00105,6,129
AB-B-00106,3,350

В данном примере должен получиться output.csv:

product_id,model,sku,upc,ean,jan,isbn,mpn,location,quantity,stock_status_id,image,manufacturer_id,shipping,price,points,tax_class_id,date_available,weight,weight_class_id,length,width,height,length_class_id,subtract,minimum,sort_order,status,viewed,noindex,date_added,date_modified
10000,AAA14223,AA-A-14223,,,,,,,5,7,catalog/4U/none.jpg,11,1,534,0,0,2017-09-17,0.00000000,0,0.00000000,0.00000000,0.00000000,0,1,1,1,1,0,1,2017-09-17 17:31:04,2017-09-17 17:31:04
10001,AAA20088,AA-A-20088,,,,,,,0,5,catalog/4U/none.jpg,11,1,0.0000,0,0,2017-09-17,0.00000000,0,0.00000000,0.00000000,0.00000000,0,1,1,2,1,0,1,2017-09-17 17:31:04,2017-09-17 17:31:04
10002,AAA28049,AA-A-28049,,,,,,,0,5,catalog/4U/none.jpg,11,1,0.0000,0,0,2017-09-17,0.00000000,0,0.00000000,0.00000000,0.00000000,0,1,1,3,1,0,1,2017-09-17 17:31:04,2017-09-17 17:31:04
10003,AAA57687,AA-A-57687,,,,,,,0,5,catalog/4U/none.jpg,11,1,0.0000,0,0,2017-09-17,0.00000000,0,0.00000000,0.00000000,0.00000000,0,1,1,4,1,0,1,2017-09-17 17:31:04,2017-09-17 17:31:04

Neuro75
() автор топика

Это легко делается одним лишь awk'ом

В секции BEGIN читается в hash файл price.csv

Далее для каждой строки файла input.csv проверяется наличие нужного столбца в хеше и подставляется значение из хеша в соотв. поле.

Дел на десяток строк кода

futurama ★★★★★
()
Ответ на: комментарий от futurama

Дел на десяток строк кода

Если не сложно, не могли бы помочь? Простые вещи на awk я кое-как могу родить, но для такого мозгов не хватает.

Neuro75
() автор топика
Ответ на: комментарий от Neuro75

А где само описание?) Вроде, «если файл X строка Y содержит информацию A, то из файла Z из строки U заменить на ...». Так, чтобы было понятно, потому что это:

На выходе требуется получить файл output.csv идентичный input.csv, в котором при наличии в файле price.csv позиции (столбец 3 и 1 соответственно) значение столбца 10 меняется на значение столбца 2 price.csv умноженное на 1,2, столбца 11 - с 5 на 7, столбца 15 - на значение столбца 3 price.csv.

мне лично не понятно.

Niroday
()
Ответ на: комментарий от Niroday

Значения в столбце 3 файла input.csv и столбце 1 файла price.csv уникальны (не повторяются).
Сравнение происходит по указанным столбцам.
1. Если строка input.csv в третьем столбце содержит значение, имеющееся в первом столбце какой-либо строки price.csv, то в этой строке input.csv необходимо:
а) значение столбца 10 заменить на значение столбца 2 price.csv;
б) значение столбца 11 заменить на цифру 7;
в) значение столбца 15 заменить на значение столбца 3 price.csv умноженное на 1,2;
2. Если строка input.csv в третьем столбце содержит значение, не встречающееся ни в одной строке input.csv, то ее нужно оставтиь без изменений;
3. Вывод необходимо направить в файл output.csv.

Neuro75
() автор топика
Ответ на: комментарий от Neuro75
awk -F',' 'BEGIN {OFS=","; 
                  while(getline < "price.csv") {
                      f[$1]=$2;
                      p[$1]=$3
                  }
                 };
         f[$3] != "" {
                       $10=f[$3];
                       $11=7;
                       $15=p[$3]
                     };
          { print }' input.csv  > output.csv

awk -F',' 'BEGIN {OFS=","; while(getline < "price.csv") {f[$1]=$2; p[$1]=$3}}; f[$3] != "" {$10=f[$3]; $11=7; $15=p[$3]}; {print}' input.csv
futurama ★★★★★
()
Ответ на: комментарий от futurama

Огромнейшее Вам спасибо!
Если вдруг кто-нибудь будет использовать в дальнейшем, то для умножения подставляемого значения на заданную величину (условие 1в)), в третьей снизу строке кода:

$15=p[$3]*1.2
Тоже самое с округлением до целого:
$15=int(p[$3]*1.2)
Округляет почему-то вниз, как округлять вверх не нашел.

Neuro75
() автор топика
Ответ на: комментарий от futurama

Плохо быть тупым. Код замечательно работает, все в соответствии с ТЗ, но почему и как он работает, понять не могу.
Ушел читать маны.

Neuro75
() автор топика
Ответ на: комментарий от Neuro75

Округляет почему-то вниз, как округлять вверх не нашел.

int(expr) Truncate to integer.

$15=int(p[$3]*1.2 + 0.5)

futurama ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.