Intereting Posts
Возможно ли настроить «масштабированный» рабочий стол в xorg.conf, аналогичный использованию опции xrandr scale-from? Debian Запуск задания выполняется для автоматических обновлений i3wm: запуск приложений без атрибута класса на определенных рабочих пространствах Как запустить команду SSH для установки StrictHostKeyChecking = no? Сложность установки и компиляции Dada Engine на OSX Как получать файлы через bluetooth в Centos? Обновите OpenGL от 1,2 до 2 для Nvidia GT218 Монетный двор 15 Второй размер окна монитора Сценарий Bash для запуска команд tmux и issue Драйвер ведомого устройства DRM Устанавливать некоторые порты брандмауэра только для подключения к локальной сети? Как определить причину использования большой буферной памяти? rdesktop: ошибка при загрузке разделяемых библиотек Объединить содержимое двух разделов в один особый раздел Как добавить несколько user.rules в ufw?

awk ищет и заменяет строку в определенном столбце файла CSV

У меня есть CSV-файл с 17 столбцами и миллионами строк. Я хочу найти определенную строку в 16-м столбце и заменить все экземпляры этой строки другой строкой. Поскольку в остальной части программы используется скрипт bash, я подумал, что вместо поиска и замены в Python используйте awk Моя текущая ОС Rhel6.

Ниже приведен пример вывода моих данных:

SUBSCRIBER_ID|ACCOUNT_CATEGORY|ACCOUNT_ACTIVATION_DATE|PACKAGE_NAME|PACKAGE_TYPE|DURATION|ACTIVE_DATE|INACTIVE_DATE|STB_NO|PRIMARY_SECONDARY|MODEL_TYPE|VC_NO|MULTIROOM|STB_TYPE|IPKG|SERVICE_STATE|CURRENT_STATUS 1001098068|ResidentialRegular|01/20/2007|Annual package 199 May17 pack|Basic Package|Annual|08/28/2017||027445053518|Primary|Pace - 31|000223871682|Yes|AMP|Package 199 pack|Market1|Active 1001098068|ResidentialRegular|01/20/2007|Annual Pack|Premium Package|Annual|08/28/2017||027445053518|Primary|Pace - 31|000223871682|Yes|AMP|English Movies pack|Market1|Active 1001098068|ResidentialRegular|01/20/2007|Annual SingleUnit Jun17 Pack|Secondary Pack|Annual|08/28/2017||032089364015|Secondary|Kaon|000017213968|Yes|AMP|SingleUnit|Market2|Active 

В этом 16-м столбце находится Market, в котором я хочу изменить Market1 на MarketPrime . Название файла: marketinfo_2018-06-26.csv

Я попробовал следующий код:

 awk -F '| +' '{gsub("Market1","MarketPrime",$16); print}' OFS="|" marketinfo_2018-06-26.csv > marketinfo_2018-06-26.csv 

Это работает без какого-либо вывода, но строка Market1 все еще остается.

 awk -F '|' -v OFS='|' '$16 == "Market1" { $16 = "MarketPrime" }1' file.csv >new-file.csv 

Единственная реальная проблема в вашем коде состоит в том, что вы устанавливаете разделитель входного файла не просто | но и в космос. Это приведет к тому, что пробелы будут считаться разделителями полей в данных, и будет невероятно сложно определить, какой правильный номер поля (поскольку некоторые поля содержат переменное количество пробелов).

Вы также не можете перенаправить на то же имя файла, которое используете для чтения. Это приведет к тому, что shell сначала обрежет (очистит) выходной файл, и ваша программа awk будет иметь данных для чтения.

Ваш код выполняет замену регулярного выражения. Это нормально, но вы должны знать, что если 16-е поле окажется чем-то вроде Market12 или TheMarket1 , оно вызовет замену из-за отсутствующих опорных точек. Было бы безопаснее использовать ^Market1$ в качестве выражения для замены или использовать сравнение строк.

Команда awk выше использует только | в качестве разделителя полей, а затем выполняет сравнение строк с 16-м полем. Если это поле Market1 , оно установлено в MarketPrime .

Конечный 1 в конце кода awk приводит к печати каждой записи (измененной или нет).

Проблема с разделителем полей ввода.

Поскольку вы хотите использовать несколько разделителей полей (что не обязательно), количество полей в каждой строке отличается, как показано ниже.

 $ awk -F '[| +]' '{print NF}' test.csv 17 26 23 21 

если вы используете только | как IFS, тогда ваш код будет работать. Поскольку каждая строка имеет 17 полей, как показано ниже.

 awk -F "|" '{print NF}' test.csv 17 17 17 17 

Решение 1 : с несколькими IFS.

 awk -F '[| +]' '{gsub("Market1","MarketPrime",$(NF-1)); print}' OFS="|" test.csv SUBSCRIBER_ID|ACCOUNT_CATEGORY|ACCOUNT_ACTIVATION_DATE|PACKAGE_NAME|PACKAGE_TYPE|DURATION|ACTIVE_DATE|INACTIVE_DATE|STB_NO|PRIMARY_SECONDARY|MODEL_TYPE|VC_NO|MULTIROOM|STB_TYPE|IPKG|SERVICE_STATE|CURRENT_STATUS 1001098068|ResidentialRegular|01/20/2007|Annual|package|199|May17|pack|Basic|Package|Annual|08/28/2017||027445053518|Primary|Pace|-|31|000223871682|Yes|AMP|Package|199|pack|MarketPrime|Active 1001098068|ResidentialRegular|01/20/2007|Annual|Pack|Premium|Package|Annual|08/28/2017||027445053518|Primary|Pace|-|31|000223871682|Yes|AMP|English|Movies|pack|MarketPrime|Active 1001098068|ResidentialRegular|01/20/2007|Annual SingleUnit Jun17 Pack|Secondary Pack|Annual|08/28/2017||032089364015|Secondary|Kaon|000017213968|Yes|AMP|SingleUnit|Market2|Active 

Решение 2 : с фиксированным полем 16

 awk -F '|' '{gsub("Market1","MarketPrime",$16); print}' OFS="|" test.csv SUBSCRIBER_ID|ACCOUNT_CATEGORY|ACCOUNT_ACTIVATION_DATE|PACKAGE_NAME|PACKAGE_TYPE|DURATION|ACTIVE_DATE|INACTIVE_DATE|STB_NO|PRIMARY_SECONDARY|MODEL_TYPE|VC_NO|MULTIROOM|STB_TYPE|IPKG|SERVICE_STATE|CURRENT_STATUS 1001098068|ResidentialRegular|01/20/2007|Annual package 199 May17 pack|Basic Package|Annual|08/28/2017||027445053518|Primary|Pace - 31|000223871682|Yes|AMP|Package 199 pack|MarketPrime|Active 1001098068|ResidentialRegular|01/20/2007|Annual Pack|Premium Package|Annual|08/28/2017||027445053518|Primary|Pace - 31|000223871682|Yes|AMP|English Movies pack|MarketPrime|Active 1001098068|ResidentialRegular|01/20/2007|Annual SingleUnit Jun17 Pack|Secondary Pack|Annual|08/28/2017||032089364015|Secondary|Kaon|000017213968|Yes|AMP|SingleUnit|Market2|Active 

Ради ясности для тех, кто может столкнуться с подобными проблемами:

Оба эти ответа работали для этого сценария:

Кусалананда ответ:

 awk -F '|' -v OFS='|' '$16 == "Market1" { $16 = "MarketPrime" }1' file.csv >new-file.csv 

Мой пересмотренный ответ основан на ответе Кусалананды:

 awk -F '|' '{gsub("Market1","MarketPrime",$16); print}' OFS="|" marketinfo_2018-06-26.csv > marketinfo_2018-06-26.csv