Jak mogę wyświetlać cytaty, gdy używam AWK do wyszukiwania i zastępowania?

0

Obecnie używam AWK, aby znaleźć i zastąpić część pierwszych trzech wystąpień ciągu. Ciąg jest sformatowany jako taki, aw pliku znajduje się wiele takich ciągów:

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

Za pomocą tego linku udało mi się znaleźć metodę użycia AWK do znalezienia i zastąpienia pierwszych trzech instancji ciągu. Zmieniłem go na to, co musiałem zrobić, a fragment mojego skryptu znajduje się poniżej:

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

Celem powyższego kodu jest dopasowanie w dowolnym wierszu zawierającym tempID i zastąpienie liczby przypisanej do tempID wartością przechowywaną w zmiennej o nazwie $id. Znajdź i zamień działa dobrze, ale wydaje mi się, że jedynym problemem jest to, że bez względu na to, jak je zbuduję, dane wyjściowe wypisują $ id bez cudzysłowów. Próbowałem uciec od cytatów i wstawiać pojedyncze tiki, ale niezależnie od tego, czy zmieniono wiersz na:

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

Próbowałem usunąć podwójne cudzysłowy wokół części zamiennej i nadać jej taką strukturę tempID="$id", ale niestety to po prostu zastępuje numer identyfikacyjny ciągiem $id.

Daj mi znać, jeśli istnieje sposób, aby znaleźć i zastąpić wartość tempID i otoczyć wartość cudzysłowami. Nie utknąłem z AWK, więc każda inna metoda z jakimkolwiek innym narzędziem, takim jak sed, również działałaby dobrze.

AndreasKralj
źródło

Odpowiedzi:

0

W twoim poleceniu są cytaty interpretowane i usuwane przez powłokę, są cytaty interpretowane i usuwane przez awk, wtedy potrzebujesz cytatów, które przetrwałyby. Powinieneś uciec od nich:

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

Wyjaśnienie. Twoje oryginalne polecenie jest jak

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            ^^^

A to jest ulepszone polecenie:

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              ^^^

Aby zmniejszyć szał cytowania, możesz użyć -vopcji, aby przekazać zmienną do awk. Wówczas nie musisz zamykać i ponownie otwierać pojedynczych cudzysłowów tylko w połowie sekwencji, aby pozwolić rozszerzeniu powłoki $id. Zamiast tego niecytowany (jak awkwidzi) idjest rozwijany awksamodzielnie. Podwójne cudzysłowy, które musimy dodać, powinny być poprzedzone znakami ucieczki:

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
źródło
Dziękuję Ci bardzo! Awk -v było właśnie tym, czego potrzebowałem!
AndreasKralj
0

Aby osiągnąć to, co chcesz zrobić, musisz:

W przypadku podwójnych cytatów:

  • AWK: Unikaj podwójnych cudzysłowów "w innych podwójnych cudzysłowach.
    $1 $2=> foobar
    $1" __"$2"__"=> foo __bar__
    $1" \""$2"\""=>foo "bar"

W przypadku pojedynczych cytatów:

  • Powłoka: Wyjdź '…'z całego skryptu awk, używając innego zestawu '…'.
    'escaped 'unescaped' escaped'
    '$LINUX '$OSTYPE' $CPUTYPE'=>$LINUX linux-gnu $CPUTYPE

  • Shell: Ucieczka, 'którą chcesz wydrukować dosłownie.
    'apostrophe that'\''s literal'=>apostrophe that's literal

Na przykład

echo foo bar | awk '{print "\""$1"\" '\''"$2"'\''"}'
"foo" 'bar'
AZ
źródło
Innym sposobem są kody ósemkowe lub szesnastkowe w podwójnych cudzysłowachecho foo bar | awk '{print "\x22"$1"\042","\x27"$2"\047"}'
Paulo