Use sed para adicionar caracteres na n'ésima posição da string correspondente

5

Eu preciso adicionar um caractere na n'ésima posição (neste caso, a segunda) de uma string correspondente. Por exemplo, em um arquivo text.txt eu gostaria de adicionar um N antes da string e depois do " apenas nas strings que contêm blah

text.txt:

"1blah8","na","8blah4"  
"2blah5","na","10blah4"  
"5blah5","na","1blah234"  

Eu quero pegar um text2.txt:

"Ν1blah8","na","Ν8blah4"  
"Ν2blah5","na","Ν10blah4"  
"Ν5blah5","na","Ν1blah234"  

Eu tentei sed 's/.*blah.*/N&/' text.txt > text2.txt mas eu recebo o N antes do " e somente na primeira string encontrada de cada linha.

    
por Minos Matsoukas 05.02.2017 / 14:10

4 respostas

6

Outra abordagem:

$ sed 's/"\([^"]*blah[^"]*"\)/"N/g' test.txt 
"N1blah8","na","N8blah4"  
"N2blah5","na","N10blah4"  
"N5blah5","na","1blah234

A regex está procurando por " , em seguida, 0 ou mais caracteres não- " seguidos por blah e, em seguida, 0 ou mais não " novamente. Por causa dos parênteses, isso é capturado e pode mais tarde ser chamado de . Portanto, o comando substituirá o padrão correspondente por si mesmo ( ), mas com "N anexado. É por isso que o primeiro " está fora dos parênteses. O modificador /g no final faz com que ele subsstitua todas as cadeias correspondentes em cada linha.

Se a sua versão sed oferecer suporte, você poderá simplificá-la para:

sed -E 's/"([^"]*blah[^"]*")/"N/g'
    
por 05.02.2017 / 15:09
5

Para obter sed para repetir a substituição de todas as correspondências em uma linha, adicione o sinalizador g após o último / :

$ sed 's/[^"]*blah/N&/g' test.txt

O g flag fará com que a substituição seja feita "para todas as correspondências não sobrepostas da expressão regular, não apenas a primeira" (citação do manual em meu sistema).

Eu também mudei a expressão regular um pouquinho para que todos os caracteres que não são " antes de blah sejam correspondidos. Dessa forma, a substituição inserirá o N logo antes do primeiro dígito, logo após o " .

    
por 05.02.2017 / 14:16
2

A análise e o processamento de CSV podem ser complexos. Aqui está um perlineriner que coloca o N na frente da coluna um e três, independentemente do conteúdo:

Etapa 1, tire aspas duplas:

@F = map { /"(.*)"/ } @F;

Etapa 2, inserindo o N na coluna um e três

$F[0,2] =~ s/^/N/;

Etapa 3, junte-se à matriz como CSV

printf qq("%s"\n), join q(","), @F

run perl:

perl -F, -ane '@F = map { /"(.*)"/ } @F; $F[0,2] =~ s/^/N/; printf qq("%s"\n), join q(","), @F' csvfile

Editar: nova abordagem para evitar o risco de segurança da expressão eval (obrigado, obrigado).

    
por 05.02.2017 / 14:50
2

Se você quiser inserir após o caractere n th (onde n é um valor arbitrário), evite sed . Existem ferramentas melhores para este trabalho (como awk ou perl , python etc) por ex. com awk , você pode usar uma variável n para inserir STRING após o caractere n th em cada campo que corresponda a PATTERN :

awk -vn=2 'BEGIN{FS=OFS=","}{for (i=1; i<=NF; i++){ if ($i ~ /PATTERN/){
h=substr($i,1,n);t=substr($i,n+1,length($i));$i=h "STRING" t}}};1' infile

Isto assume que seu arquivo é um simples arquivo csv (sem vírgulas embutidas em seus campos).

    
por 05.02.2017 / 20:11