Com um único awk :
awk -F'[:,]' '{$3=$2":"$3}1' OFS=, infile
AAA, BBB, BBB:XXX, CCC, DDD, EEE, FFF, GGG, HHH
Arquivo de entrada:
AAA, BBB:XXX, CCC, DDD, EEE, FFF, GGG, HHH
O resultado deve ser:
AAA, BBB, BBB:XXX, CCC, DDD, EEE, FFF, GGG, HHH
Eu pensei em algo como:
awk -F, '{n=split($2,a,":"); a[n]} {$2=$NF","$2}1' OFS=,
Mas o primeiro "split" usa o lado direito do delimitador em vez do esquerdo e a cópia no final copia o HHH em vez do BBB.
Com um único awk :
awk -F'[:,]' '{$3=$2":"$3}1' OFS=, infile
AAA, BBB, BBB:XXX, CCC, DDD, EEE, FFF, GGG, HHH
Tente isto:
awk -F, '{n=split($2,a,":"); a[n]} {$2=a[1]","$2}1' OFS=, file
AAA, BBB, BBB:XXX, CCC, DDD, EEE, FFF, GGG, HHH
A atribuição do último campo e um segundo campo a $ 2 ( $2=$NF","$2 ) em vez de atribuir a divisão em a com o segundo campo ( $2=a[1]","$2 )
Uma abordagem simples não-awk
$ ( cut -f1 -d: file ; cut -f2- -d, file ) | paste -sd,
AAA, BBB, BBB:XXX, CCC, DDD, EEE, FFF, GGG, HHH
$
Uma rápida opção sed
sed -r 's/, \w+/&&/'
A expressão \w+ corresponde a alfanuméricos (no seu exemplo, o BBB ), mas não a pontuação ou espaço em branco. O & representa a correspondência inteira.
Exemplo
echo 'AAA, BBB:XXX, CCC, DDD, EEE, FFF, GGG, HHH' | sed -r 's/, \w+/&&/'
AAA, BBB, BBB:XXX, CCC, DDD, EEE, FFF, GGG, HHH
$ awk -F, -v OFS=, '{ for (i=1; i<=NF; ++i) if (split($i, a, ":") > 1) $i = a[1] OFS $i } 1' file
AAA, BBB, BBB:XXX, CCC, DDD, EEE, FFF, GGG, HHH
Você terá que fazer uma iteração em todos os campos e, quando encontrar um campo que se divida em mais de uma string ao dividir em : , será necessário preceder a primeira parte dessa string dividida ao valor dessa campo.
Se você sabe que sempre será o segundo campo:
$ awk -F, -v OFS=, '{ split($2, a, ":"); $2 = a[1] OFS $2 } 1' file
AAA, BBB, BBB:XXX, CCC, DDD, EEE, FFF, GGG, HHH
Em seu código, n será o número de sequências de caracteres nas quais os dados foram divididos. Portanto, a[n] será a última string% (mais à direita) : -eliminada em $2 .
Usando sed :
$ sed 's/\([^,: ]*\):/, &/g' file
AAA, BBB, BBB:XXX, CCC, DDD, EEE, FFF, GGG, HHH
Isso substituirá qualquer string que não contenha , , : ou espaço, e que sejam seguidos imediatamente por um : com ela mesma duas vezes (a segunda vez com o% final: incluído).
Remova o g no final do comando s se você espera apenas fazer uma única substituição (como no seu exemplo).
Tags text-processing awk sed cut csv-simple