Tenho um arquivo contendo valores que devem ser obscurecidos (substituídos por XX), mas eles nem sempre estão na mesma posição dentro de toda a linha, e não sei seu conteúdo. O que sei, no entanto, é sua posição relativa a uma correspondência específica.
Por exemplo, quero que o terceiro e o quarto número depois de "00 00" sejam substituídos por XX
Original:
AA BB CC 00 00 01 02 03 04 05 06 07
AA BB CC DD EE FF 00 00 08 09 10 11 12 13 14
Saída desejada:
AA BB CC 00 00 01 02 XX XX 05 06 07
AA BB CC DD EE FF 00 00 08 09 XX XX 12 13 14
Eu tentei com awk, mas só consegui me posicionar em relação ao começo da linha. Existe uma maneira de indexar $2 e $3 de uma correspondência específica, por exemplo?
Edição: só pode haver uma ocorrência de 00 00
na linha, ela não pode conter, 00 00 00
não há necessidade de se preocupar com correspondência inicial ou final.
Minha tentativa (embaraçosa) até agora foi:
cat file | awk -F'00 00' '{print $2}' | awk '{gsub ($3,"XX",$0);gsub ($4,"XX",$0)}1'
Além dos vários awks, também perco o início das linhas, pois tudo antes da partida é descartado pelo meu primeiro awk
É mais fácil com
sed
ouperl
do que com,awk
a menos que você tenha umawk
que suporte a extensãogawk
'sgensub()
:Com POSIX
awk
, você pode fazer:Aqui está uma abordagem awk:
A ideia é iterar sobre todos os campos (
for(i=1; i<=NF; i++)
;NF
é o número de campos), e procurar por casos onde o campo atual ($i
) e o próximo ($(i+1)
) são ambos definidos para a string00
. Então, mudamos o 3º e 4º campo paraXX
($(i+4)=$(i+5)="XX"
; usando+4
and+5
já que estou contando do primeiro00
, não do segundo). Finalmente, imprimimos tudo. A ação padrão paraawk
quando uma expressão é avaliada como true é imprimir a linha, então o simples1
, que é sempre true, é frequentemente usado como uma abreviação paraprint
.Note que isso tem a desvantagem de substituir seu separador de campo por um espaço. Neste exemplo, isso não parece ser um problema, mas se for, apenas especifique os separadores de entrada e saída. Então, se sua entrada tivesse vírgulas que você deseja manter, você faria:
Você também pode tratar isso como uma substituição simples e fazer algo como:
Ou
Usando
awk
:Supondo que apenas números sejam repetidos depois de
00 00
.Este comando usa
gawk
a função split do .Primeiro, o registro atual(
$0
) ésplit
. Esta função interna cria dois arrays, a saber,a
eseps
(o array separador). Então$0
é definido como""
. Entãosub()
é usado para substituirvar
com campos a serem substituídos no arrayseps
.O
awk
comando divide os campos pelaGNU awk
função interna dosplit
.n = dividir(s, matriz, sep)
divide a string s em array[1] , ..., array[n] . O número de elementos encontrados é retornado. Se o argumento sep for fornecido, ele será usado como separador de campo; caso contrário, FS será usado.
Do Awk — Uma Linguagem de Processamento e Varredura de Padrões
split( string, array [, fieldsep [, seps ] ] )
Divida a string em pedaços separados por fieldsep e armazene os pedaços na matriz e as strings separadoras na matriz seps .
Do livro Effective AWK Programming , de Arnold Robbins.
Usando qualquer awk: