Substituindo um grupo capturado usando o SED

3

xxxxxx15 |xxxxxx02|RM99999 |xxxxx |Ankur |xxxxx |xxxxxxxx|M|xxxxxxxx| | | |xxxxxxx|xxx|xxxxxxxx| |10 |New York| 23.00|F|P| | |NA

Quero substituir 10 por 65, o closet que eu tenho é sed -i '/^.\{20\}RM99999/ s/^\(?:[^|]*\|\)\{16\}\([^|]*\)/5/' test.txt

Mas substitui, o primeiro caractere com 65 ( RM99999 pode estar em mais locais, mas precisa substituir a linha que tem RM99999 no 20º caractere)

    
por ankur 13.07.2015 / 09:16

2 respostas

5

parece um problema XY.

por que não tentar com o awk?

awk -F\| -v OFS=\| '$3=="RM99999" && $17 == 10 { $17=65 } {print ; } '

onde

  • -F\| diz ao awk para usar | como separador de campos ( \ tell shell para escape | )
  • -v OFS=\| diz ao awk para usar | como o separador de campo quando os registros são gerados
  • $3=="RM99999" && $17 == 10 seleciona linha com terceiro arquivado como RM99999 e décimo sétimo como 10
  • $17 = 65 substitui por 65
  • { print ; } imprime todos os padrões, alterados e inalterados
por 13.07.2015 / 09:38
5
sed '/^.\{19\}RM99999/s/10/65/' <in >out

Substituirá a primeira ocorrência da string 10 pela string 65 em uma linha onde a string RM99999 começa no 20º caractere.

Acho que alguns acham que o 17º campo deve ser substituído. Eu realmente não entendo porque eu não posso ver isso na pergunta, mas se é o que você quer ...

sed '/^.\{19\}RM99999/s/[^|]*/65/17' <in >out

... que substituirá o campo 17th | delimitado pela string 65 em uma linha onde a string RM99999 começa no 20º caractere.

Eu meio que estou apenas agarrando canudos, mas talvez eles signifiquem apenas 10 e apenas no 17º campo, e apenas em linhas onde RM99999 inicia 20 caracteres em? É um pouco mais difícil ...

sed -e'/^.\{19\}RM99999/s/|/|\n/16' \
    -e's/\n\([^|]*\)10/5/;s/\n//' <in >out

... mas isso vai fazer isso. Venha para pensar sobre isso, parece um pouco mais parecido com o seu próprio código. Talvez seja o que é desejado depois de tudo.

Este é um pouco mais direto ...

sed -e'/^.\{19\}RM99999/!b'    \
    -e's/|\([^|]*10\)*/&\n/16' \
    -e's/10\n/65/;s/\n//'

E isso acontece de uma só vez - se a contagem de campos for fixa, ou seja,

sed -e'/^.\{19\}RM99999/s/10\([^|]*\(|[^|]*\)\{7\}\)$/65/'

Você pode fazer a mesma coisa no front end, é claro ...

sed -e'/^.\{19\}RM99999/s/^\([^|]*\(|[^|]*\)\{16\}\)10/5/'

Mas como há mais da metade dos campos para a cauda, provavelmente é melhor não saber se ela pode ser ajudada.

E é um pouco mais fácil escrever com a sintaxe regexp estendida:

sed -Ee'/^.{19}RM99999/s/10([^|]*(\|[^|]*){7})$/65/'
    
por 13.07.2015 / 09:48

Tags