Обновите столбец текстового файла и запишите в выходные данные имена переменных

У меня есть запись предметов с их идентификатором и ценой, и я пытаюсь обновить цену некоторых из этих предметов в соответствии с другим «справочным файлом», формат которого — Item# NewPrice OutFile. В конечном итоге у нас будет столько выходных записей, сколько # строк в ref-файле (здесь 4 выхода). OutFiles будут аналогичны исходным файлам, за исключением скорректированного элемента. Ниже мои файлы и скрипт awk, который не работает. Я ценю вашу помощь.

Main file  [Item # current_value]:
Item  1  20 
Item  2  30
Item  3  40

Reference file  [Item# new_value outputfile]
1  22  It1_22
1  25  It1_25
2  32  It2_32
3  45  It3_45

Expected Output files:
(It1_22)
Item,1,22
Item,2,30
Item,3,40

(It1_25)
Item,1,25
Item,2,30
Item,3,40

(It2_32)
Item,1,20
Item,2,32
Item,3,40

(It3_45)
Item,1,20
Item,2,30
Item,3,45

Мой скрипт не генерирует никаких файлов:

awk 'BEGIN{OFS = ","};FNR == NR{a[$1]=$2;d=$3;next} $2 in a{print $1,$2,a[$2];next}1' ref  main > d

Объясните свою логику для желаемого результата. It1_22 заменяет цену товара 1 с 20 на 22. Хорошо. Но It2_34 заменяет цену товара 1 и цену товара 2. Там должно быть 5 файлов нет? Или вам нужна самая высокая цена только для каждого товара? Самая высокая цена за пункт 1 составляет 26, так что ...

Nic3500 06.04.2023 09:21

Я расширил все нужные мне выходные файлы. Надеюсь, это объясняет мою логику. Для любого вывода будет изменен только назначенный элемент в справочном файле. Сценарий должен просматривать справочный файл и обновлять только определенный элемент в каждой строке.

EverLearner 06.04.2023 15:15

Хорошо объяснил, и вы получили ответ быстро. Я бы и сам не справился лучше (вероятно, даже хуже).

Nic3500 06.04.2023 21:18
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
75
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

вот одно решение без какой-либо обработки ошибок для отсутствующих значений и т. д. Чтобы сохранить порядок файла данных, свяжите каждый с номером строки и восстановите во время печати.

$ awk -v OFS=, 'NR==FNR{k=$2; n[k]=$1; v[k]=$3; ord[NR]=k; next}                        
                       {for(i=1;i<=length(ord);i++) 
                          {k=ord[i]; 
                           print n[k],k,k==$1?$2:v[k] > $3}}' mainfile reffile 
                                        
$ head It*
==> It1_22 <==
Item,1,22
Item,2,30
Item,3,40

==> It1_25 <==
Item,1,25
Item,2,30                                                                                                      
Item,3,40                                                                                                      
                                                                                                               
==> It2_32 <==                                                                                                 
Item,1,20                                                                                                      
Item,2,32                                                                                                      
Item,3,40                                                                                                      
                                                                                                               
==> It3_45 <==                                                                                                 
Item,1,20                                                                                                      
Item,2,30                                                                                                      
Item,3,45       

                 

Большое спасибо. Это умный код. Единственное, выходные строки идут в обратном порядке, т.е. Item,3,40 , затем Item2 и последний Item 1. Легко ли это исправить?

EverLearner 06.04.2023 16:13

поскольку массивы на самом деле являются ассоциативными массивами, порядок итерации может отличаться от порядка вставки, хотя для небольшого количества записей с целочисленными ключами его следует сохранить. Несмотря на это, я добавил еще один массив, чтобы сохранить первоначальный порядок.

karakfa 06.04.2023 17:10

Я получаю синтаксическую ошибку с новым кодом: Синтаксическая ошибка Контекст: >>> ,NR==FNR{k=$2; п[к]=$1; v[k]=$3; порядок[ <<<

EverLearner 06.04.2023 17:22

выглядит нормально для меня, убедитесь, что вы правильно скопировали / вставили. Кажется, перед NR стоит запятая, которой не должно быть в вашем сообщении об ошибке.

karakfa 06.04.2023 17:29

Я подумал, что это как-то связано с оператором ord[NR]=k. Не уверен, что?

EverLearner 06.04.2023 18:30

Это не должно быть реальной проблемой со сценарием в том виде, в котором он написан, но ord() — это имя функции в библиотеке ordchr GNU awk, поэтому обычно избегайте его использования в качестве имени переменной.

Ed Morton 07.04.2023 02:47
length(ord) будет терпеть неудачу в некоторых awks, поскольку это неопределенное поведение в POSIX, где length() может принимать только строковый аргумент, а не массив.
Ed Morton 07.04.2023 02:51

Вы также можете столкнуться с ошибкой «слишком много открытых файлов» из-за того, что не закрыли выходные файлы по ходу работы, это зависит только от того, сколько выходных файлов создает скрипт и какой вариант awk вы используете.

Ed Morton 07.04.2023 02:54

Вы также можете столкнуться с проблемами с тернарным выражением без скобок в некоторых контекстах в некоторых awks, см. unix.stackexchange.com/questions/588714/….

Ed Morton 07.04.2023 02:57

Не могли бы вы вкратце объяснить, как работала первая версия скрипта? awk -v OFS=, 'NR==FNR {n[$2]=$1; v[$2]=$3; next} {for(k in n) print n[k],k,k==$1?$2:v[k] > $3}' main ref

EverLearner 07.04.2023 09:58
Ответ принят как подходящий

Использование GNU awk для массивов массивов и неограниченного количества открытых файлов:

$ cat tst.awk
BEGIN { OFS = "," }
NR == FNR {
    vals[$3][$1] = $2
    next
}
{
    for ( fname in vals ) {
        print $1, $2, ($2 in vals[fname] ? vals[fname][$2] : $3) > fname
    }
}

$ awk -f tst.awk ref main

$ head It*
==> It1_22 <==
Item,1,22
Item,2,30
Item,3,40

==> It1_25 <==
Item,1,25
Item,2,30
Item,3,40

==> It2_32 <==
Item,1,20
Item,2,32
Item,3,40

==> It3_45 <==
Item,1,20
Item,2,30
Item,3,45

Вы можете сделать то же самое с помощью любого awk, просто он будет работать немного медленнее, так как должен открывать/закрывать каждый выходной файл для каждой записи, в отличие от gawk, где он будет делать это только при необходимости, чтобы избежать «слишком большого количества открытых файлов». файлы» ошибка:

$ cat tst.awk
BEGIN { OFS = "," }
NR == FNR {
    vals[$3,$1] = $2
    fnames[$3]
    printf "" > $3
    close($3)
    next
}
{
    for ( fname in fnames ) {
        print $1, $2, ((fname,$2) in vals ? vals[fname,$2] : $3) >> fname
        close(fname)
    }
}

Эд, большое спасибо за сценарии. Интересно, не могли бы вы вкратце объяснить поток первой версии скрипта от karakfa? awk -v OFS=, 'NR==FNR {n[$2]=$1; v[$2]=$3; next} {for(k in n) print n[k],k,k==$1?$2:v[k] > $3}' main ref

EverLearner 09.04.2023 13:48

Пожалуйста. Вы должны попросить @karakfa объяснить их сценарий.

Ed Morton 09.04.2023 15:04

Ваш последний код быстрый и полезный. Я пытаюсь понять это. Можете ли вы объяснить логику и поток?

EverLearner 12.04.2023 03:18

Как ни странно, я получаю сообщение об ошибке при повторном запуске кода как tst.awk ref main --> C:/Program Files (x86)/MKS Toolkit/mksnt/awk.exe: Синтаксическая ошибка Контекст: >>> \ << < Есть мысли?

EverLearner 12.04.2023 04:27

Поскольку в моем сценарии нет \, я думаю, вы неправильно скопировали/вставили его и куда-то добавили \.

Ed Morton 12.04.2023 04:30

Я думаю, что сценарий довольно прост после беглого взгляда на справочные страницы awk, но есть ли у вас что-то конкретное, что вы нашли в нем неясным, что вы хотели бы, чтобы я разъяснил?

Ed Morton 12.04.2023 04:32

Конкретно не могу понять vals[$3,$1] = $2. Что делает эта строка? К чему относится каждое поле?

EverLearner 12.04.2023 04:34
$1 — первое поле (значение через пробел в текущей строке ввода), $2 второе поле, $3 третье поле. vals[] — это массив, проиндексированный конкатенацией $3 и $1 и содержащий $2 по этому индексу. См. gnu.org/software/gawk/manual/gawk.html#Массивы.
Ed Morton 12.04.2023 14:24

Другие вопросы по теме