como substituir um valor por esse valor + constante

6

Eu tenho um arquivo que tem variáveis do G1 ao G229. Eu quero substituí-los com G230 para G469; como eu posso fazer isso? Eu tentei este script bash mas não funcionou:

#!/bin/bash

for num in {1..229}
  do
  echo G$num
  N=$(($num+229))
  echo G$N  
  sed -i -e 's/$G$num/$G$N/g' file
done
    
por Sadra Avestan 01.09.2017 / 00:01

3 respostas

2

sed solution. Talvez seja muito complicado e não é ideal, mas funciona. Como um experimento:).

Ele faz todas as substituições na chamada sed executando a única sequência de comando grande gerada pelo printf e paste usage. Eu queria dividir esse comando para a multilinha por legibilidade, mas não consegui - ele parou de funcionar. Então - o oneliner:

sed -i -r "$(paste -d'/' <(printf 's/%s\b\n' G{1..229}) <(printf '%s/g\n' G{230..458}))" file.txt

Ele está convertendo para o seguinte comando sed :

sed -i -r "s/G1\b/G230/g
s/G2\b/G231/g
s/G3\b/G232/g
s/G4\b/G233/g    
...
s/G227\b/G456/g
s/G228\b/G457/g
s/G229\b/G458/g" file.txt

Explicação

  1. sed -i -r "$(
  2. paste -d'/' - une as partes esquerda e direita (que são geradas em 3,4 etapas) pela barra - / e o resultado é este: s/G1\b/G230/g
  3. <(printf 's/%s\b\n' G{1..229}) - faz partes da esquerda do comando sed substitute. Exemplo: s/G1\b , s/G2\b , s/G3\b , etc.
    • \b - Corresponde a um limite de palavra; ou seja, se o caractere à esquerda for um caractere de “palavra” e o caractere à direita for um caractere de “não-palavra” ou vice-versa. Informações - extensões de expressões regulares do GNU sed.
  4. <(printf '%s/g\n' G{230..458}) - faz partes certas do comando sed substitute. Exemplo: G230/g , G231/g , G232/g , etc.
  5. )" file.txt - arquivo de entrada.

Teste

Entrada

var G1 = value;
G3 = G1 + G2; 
G3 = G1 + G2
G3 = ${G1} + G2
var G2 = value;
var G3 = value;
G224 = G3 + G215;
G124 = G124 + G215;
G124 = G124 + G12;
var G4 = value;
var G5 = value;
var G6 = value;
var G59 = value;
var G60 = value;
var G156 = value;
var G227 = value;
var G228 = value;
var G229 = value;

Resultado

var G230 = value;
G232 = G230 + G231;
G232 = G230 + G231
G232 = ${G230} + G231
var G231 = value;
var G232 = value;
G453 = G232 + G444;
G353 = G353 + G444;
G353 = G353 + G241;
var G233 = value;
var G234 = value;
var G235 = value;
var G288 = value;
var G289 = value;
var G385 = value;
var G456 = value;
var G457 = value;
var G458 = value;
    
por 01.09.2017 / 03:35
8

Isso é mais um trabalho para perl (qual GNU sed copiou esse -i a propósito):

perl -pi -e 's{\$G\K\d+}{
  if ($& >= 1 && $& <= 229) {
    $& + 229
  } else {
    $&
  }}ge' file

Observe que isso também alteraria G0001 para G230 . Se você não quiser isso, poderá alterar o \d+ para [1-9]\d* .

Com sua abordagem, mesmo que você tenha corrigido as citações, isso reescreveria o arquivo 229 vezes e também não funcionaria como você gostaria.

Um s/\$G1/\$G230/g mudaria $G12 para $G2302 e o próximo s/\$G2/\$G231/g alteraria isso para G231302 (que s/\$G23/\$G252 mudaria para G2521302 e assim por diante). / p>     

por 01.09.2017 / 00:07
3

Aspas simples na expansão da variável bash stop, de modo que o seguinte está procurando o literal $G$num a ser substituído pelo literal $G$N

sed -i -e 's/$G$num/$G$N/g' file

Você quer que a expansão do bash aconteça, então você deve usar aspas duplas e escapar quaisquer caracteres especiais manualmente:

sed -i -e "s/\$G$num/\$G$N/g" file

Você pode ver a diferença com o seguinte script:

#!/bin/bash

for num in {1..229}; do
  N=$(($num+229))
  echo '$G$num $G$N' vs "\$G$num \$G$N"
done

Produz

$G$num $G$N vs $G1 $G230
$G$num $G$N vs $G2 $G231
$G$num $G$N vs $G3 $G232
...
$G$num $G$N vs $G228 $G457
$G$num $G$N vs $G229 $G458
    
por 01.09.2017 / 00:11