Como posso obter cotações para mostrar quando estou usando o AWK para localizar e substituir?

0

Atualmente estou usando o AWK para localizar e substituir uma parte das três primeiras ocorrências de uma string. A string é formatada como tal e há muitas dessas strings no arquivo:

func(tempID="39849235",count='12');

Usando esse link , consegui encontrar um método de usar o AWK para localizar e substituir as três primeiras instâncias da string. Eu mudei para o que eu precisava fazer, e um trecho do meu script está abaixo:

id=12349876
awk 'BEGIN {matches=0}
     matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID='"$id"'"); matches++ }
     { print $0 }' filName.py >filName.py.changed

O objetivo do código acima é combinar em qualquer linha que contenha tempID e substituir o número atribuído a tempID por um valor mantido em uma variável nomeada $id. O find and replace funciona bem, mas a única questão que pareço ter é que, independentemente de como eu a estruturo, a saída imprime o $ id sem aspas. Eu tentei escapar de citações e colocar carrapatos simples, mas independentemente da linha é alterada para:

func(tempID=39849235,count='12');

Eu tentei remover as aspas duplas em torno da parte de substituição e estruturá-lo como tempID="$id", mas infelizmente isso apenas substitui o número de identificação com a seqüência de caracteres $id.

Por favor, deixe-me saber se existe uma maneira de encontrar e substituir o valor tempID e coloque o valor entre aspas. Eu não estou preso com AWK, então qualquer outro método com qualquer outro utilitário como o sed funcionaria bem também.

AndreasKralj
fonte

Respostas:

0

Em seu comando há citações interpretadas e despojadas pelo shell, há citações interpretadas e despojadas por awk, então você precisa de citações que sobreviveriam. Você deve escapar deles:

id=12349876
awk 'BEGIN {matches=0}
 matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID=\"'"$id"'\""); matches++ }
 { print $0 }' filName.py >filName.py.changed              # ^^  here ^^

Explicação. Seu comando original é como

awk 'BEGIN {matches=0} matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID='"$id"'"); matches++ } { print $0 }'
#   ^ these quotes are seen by the shell and don't get to awk                      ^^   ^^                            ^
#     these quotes get to awk and serve their purpose there      ^      ^  ^              ^
#     this variable is expanded by the shell and gets to awk as its value            ^^^

E este é o comando melhorado:

awk 'BEGIN {matches=0} matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID=\"'"$id"'\""); matches++ } { print $0 }'
#   ^ these quotes are seen by the shell and don't get to awk                        ^^   ^^                              ^
#     these quotes get to awk and serve their purpose there      ^      ^  ^                  ^
#     these quotes will appear in the output thanks to being escaped                ^        ^
#     this variable is expanded by the shell and gets to awk as its value              ^^^

Para reduzir o frenesi de citação, você pode usar a -vopção para passar a variável para awk. Então você não precisa fechar e reabrir aspas simples no meio da seqüência apenas para permitir que o shell se expanda $id. Em vez disso, sem aspas (como se awkvê) idé expandido por awkconta própria. Aspas duplas que precisamos adicionar devem ser escapadas como antes:

id=12349876
awk -v id="$id" 'BEGIN {matches=0}
 matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID=\""id"\""); matches++ }
 { print $0 }' filName.py >filName.py.changed
Kamil Maciorowski
fonte
Muito obrigado! O awk -v era exatamente o que eu precisava!
AndreasKralj
0

Para conseguir o que você quer fazer, você precisa:

Para aspas duplas:

  • AWK: Escape entre aspas duplas "dentro de outras aspas duplas.
    $1 $2=> foobar
    $1" __"$2"__"=> foo __bar__
    $1" \""$2"\""=>foo "bar"

Para aspas simples:

  • Shell: Saia do '…'seu script awk inteiro, usando outro conjunto '…'dentro dele.
    'escaped 'unescaped' escaped'
    '$LINUX '$OSTYPE' $CPUTYPE'=>$LINUX linux-gnu $CPUTYPE

  • Shell: Escape 'você quer ser impresso literalmente.
    'apostrophe that'\''s literal'=>apostrophe that's literal

Por exemplo

echo foo bar | awk '{print "\""$1"\" '\''"$2"'\''"}'
"foo" 'bar'
AZ
fonte
Outra maneira é com códigos octal ou hexadecimais entre aspas duplasecho foo bar | awk '{print "\x22"$1"\042","\x27"$2"\047"}'
Paulo