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');
Usandoesse 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 é corresponder qualquer linha contendo tempID e substituir o número atribuído a tempID por um valor mantido em uma variável chamada $id
. Localizar e substituir funciona bem, mas o único problema que parece ter é que não importa como eu o estruture, a saída imprime o $id sem aspas. Eu tentei escapar de aspas e colocar marcas únicas, mas independentemente da linha ser alterada para:
func(tempID=39849235,count='12');
Tentei remover as aspas duplas na parte de substituição e estruturá-la como tempID="$id"
, mas infelizmente isso apenas substitui o número de ID pela string $id
.
Por favor, deixe-me saber se existe uma maneira de localizar e substituir o valor tempID e colocar o valor entre aspas. Não estou preso ao AWK, então qualquer outro método com qualquer outro utilitário como sed também funcionaria bem.
Responder1
No seu comando existem aspas interpretadas e removidas pelo shell, existem aspas interpretadas e removidas por awk
, então você precisa de aspas 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ções, você pode usar -v
a opção para passar a variável para awk
. Então você não precisa fechar e reabrir aspas simples no meio da sequência apenas para permitir que o shell se expanda $id
. Em vez disso, sem aspas (como awk
é visto) id
é expandido por awk
si só. As aspas duplas que precisamos adicionar devem ter escape 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
Responder2
Para alcançar o que deseja fazer, você precisa:
Para aspas duplas:
- AWK: Escape de aspas duplas
"
dentro de outras aspas duplas.
$1 $2
=>foobar
$1" __"$2"__"
=>foo __bar__
$1" \""$2"\""
=>foo "bar"
Para aspas simples:
Shell: Saia
'…'
de todo o seu script awk, usando outro conjunto'…'
dentro dele.
'escaped 'unescaped' escaped'
'$LINUX '$OSTYPE' $CPUTYPE'
=>$LINUX linux-gnu $CPUTYPE
Shell: Escape
'
que você quer ser impresso literalmente.
'apostrophe that'\''s literal'
=>apostrophe that's literal
Por exemplo
echo foo bar | awk '{print "\""$1"\" '\''"$2"'\''"}'
"foo" 'bar'