Como substituir um determinado campo em um arquivo com base no conteúdo de outro campo?

4

Eu tenho um arquivo com o seguinte formato:

A 485C72F95C72E15C EXTERNAL
B CC32480A3247F84A SYSTEM
C EC2A63F12A63B76C EXTERNAL

Eu quero fornecer a letra na primeira coluna usando o valor da variável 'letter' e substituir o valor na segunda coluna por um valor fornecido na variável 'id'. A terceira coluna pode ou não diferir ou corresponder em qualquer caso. As primeira e segunda colunas nunca conterão espaços ou caracteres especiais.

Eu tentei usar sed , mas meu sed-fu não é strong. Eu inventei isso:

letter=A
id=MYNEWIDSTRING
sed "/$letter /s/[^ ]*/$id/2"

A saída é:

A MYNEWIDSTRING EXTERNAL
B MYNEWIDSTRING SYSTEM
C EC2A63F12A63B76C EXTERNAL

O id é substituído em duas linhas, estou assumindo que isso se deve ao fato de 'A' ser correspondido no final da string de id original.

Eu sei usar sed -i para editar o arquivo no lugar, mas não o faço ainda, já que meu comando ainda é um pouco desonesto.

Onde eu errei, ou devo usar um método diferente?

    
por Arronical 03.11.2016 / 14:37

2 respostas

5

Ancore-o ( ^ é o início da linha) para que o A seja correspondido apenas se for o primeiro caractere:

$ letter=A; id=MYNEWIDSTRING; sed "/^$letter /s/[^ ]*/$id/2" file
A MYNEWIDSTRING EXTERNAL
B CC32480A3247F84A SYSTEM
C EC2A63F12A63B76C EXTERNAL

a propósito, se você quiser passar variáveis para sed , mas precisar de citação strong, lembre-se de ativar e desativar a citação ao adicionar aspas duplas às variáveis - feio, mas provavelmente a melhor prática em geral:

sed '/^'"$letter"' /s/[^ ]*/'"$id"'/2'
    
por Zanna 03.11.2016 / 14:51
5

Sempre que você estiver lidando com dados estruturados , eu alcançarei awk ou perl em vez de sed .

Por exemplo

awk -v letter="A" -v id="MYNEWIDSTRING" ' == letter {=id}1' file
A MYNEWIDSTRING EXTERNAL
B CC32480A3247F84A SYSTEM
C EC2A63F12A63B76C EXTERNAL

ou

perl -alne '
  BEGIN{$letter = shift; $id = shift;} 
  print join " ", $F[0], $F[0] eq $letter ? $id : $F[1], @F[2..$#F]
' 'A' 'MYNEWIDSTRING' file

As versões mais recentes do GNU awk têm um sinalizador -i ( --in-place ); em outros, você precisaria usar um arquivo temporário explícito; perl deve ter um -i em qualquer caso.

    
por steeldriver 03.11.2016 / 15:03