Eu tenho um arquivo csv com 17 colunas e milhões de linhas. Quero procurar uma string específica na 16ª coluna e substituir todas as instâncias dessa string por outra string. Como o resto do programa usa o script bash, pensei em usar o awk em vez do Python search & replace. Meu sistema operacional atual é Rhel6.
A seguir está a saída de amostra dos meus dados:
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
Nesta, a 16ª coluna é Market, na qual quero alterar Market1
para MarketPrime
. O nome do arquivo émarketinfo_2018-06-26.csv
Tentei o seguinte código:
awk -F '| +' '{gsub("Market1","MarketPrime",$16); print}' OFS="|" marketinfo_2018-06-26.csv > marketinfo_2018-06-26.csv
Isso é executado sem qualquer saída, mas a string Market1
ainda permanece.
O único problema real em seu código é que você define o separador do arquivo de entrada não apenas
|
para espaços, mas também para espaços. Isso fará com que os espaços contem como separadores de campo nos dados e será incrivelmente difícil descobrir qual é o número de campo correto (já que alguns campos contêm um número variável de espaços).Você também não pode redirecionar para o mesmo nome de arquivo que você usa para ler. Fazer isso faria com que o shell primeiro truncasse (esvaziasse) o arquivo de saída e seu
awk
programa não teria dados para ler.Seu código faz uma substituição de expressão regular. Tudo bem, mas você precisa estar ciente de que, se o 16º campo for algo como
Market12
ouTheMarket1
, ele acionaria a substituição devido aos pontos de ancoragem ausentes. Seria mais seguro usar^Market1$
como a expressão para substituir ou usar uma comparação de string.O
awk
comando acima usa apenas|
como separador de campo e depois faz uma comparação de string com o 16º campo. Se esse campo forMarket1
, ele será definido comoMarketPrime
.A trilha
1
no final doawk
código faz com que todos os registros (modificados ou não) sejam impressos.O problema é com o separador de campo de entrada.
Como você deseja usar o separador de vários campos (o que não é obrigatório), o número de campos em cada linha é diferente, conforme mostrado abaixo.
se você usar apenas
|
como IFS, seu código funcionará. Uma vez que cada linha tem 17 campos como mostrado abaixo.Solução 1 : com vários IFS.
Solução 2 : com campo fixo 16
Por uma questão de clareza para outras pessoas que possam enfrentar problemas semelhantes:
Ambas as respostas funcionaram para este cenário:
A resposta de Kusalananda:
Minha resposta revisada com base na resposta de Kusalananda:
Você pode usar o abaixo
usando isso, você pode alterar qualquer palavra na lane que combine com Market1, por exemplo, se você quiser alterar a 17ª palavra, basta alterá-la para