Derzeit verwende ich AWK, um einen Teil der ersten drei Vorkommen einer Zeichenfolge zu suchen und zu ersetzen. Die Zeichenfolge ist wie folgt formatiert und die Datei enthält viele dieser Zeichenfolgen:
func(tempID="39849235",count='12');
Verwenden vondieser Linkkonnte ich eine Methode finden, mit der ich mit AWK die ersten drei Instanzen der Zeichenfolge suchen und ersetzen kann. Ich habe es so geändert, wie ich es brauchte, und unten sehen Sie einen Ausschnitt meines Skripts:
id=12349876
awk 'BEGIN {matches=0}
matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID='"$id"'"); matches++ }
{ print $0 }' filName.py >filName.py.changed
Das Ziel des obigen Codes ist es, jede Zeile mit tempID zu finden und die tempID zugewiesene Nummer durch einen Wert zu ersetzen, der in einer Variablen namens gespeichert ist $id
. Das Suchen und Ersetzen funktioniert gut, aber das einzige Problem, das ich zu haben scheine, ist, dass die Ausgabe, egal wie ich sie strukturiere, die $id ohne Anführungszeichen ausgibt. Ich habe versucht, die Anführungszeichen zu maskieren und einzelne Häkchen zu setzen, aber trotzdem ändert sich die Zeile wie folgt:
func(tempID=39849235,count='12');
Ich habe versucht, die Anführungszeichen um den Ersetzungsteil zu entfernen und ihn als zu strukturieren tempID="$id"
, aber leider wird dadurch nur die ID-Nummer durch die Zeichenfolge ersetzt $id
.
Bitte lassen Sie mich wissen, ob es eine Möglichkeit gibt, den TempID-Wert zu finden und zu ersetzen und den Wert in Anführungszeichen zu setzen. Ich bin nicht auf AWK angewiesen, daher würde auch jede andere Methode mit einem anderen Dienstprogramm wie sed problemlos funktionieren.
Antwort1
In Ihrem Befehl gibt es Anführungszeichen, die von der Shell interpretiert und entfernt werden, es gibt Anführungszeichen, die von interpretiert und entfernt werden awk
, dann brauchen Sie Anführungszeichen, die erhalten bleiben. Sie sollten sie maskieren:
id=12349876
awk 'BEGIN {matches=0}
matches < 3 && /.*tempID.*/ { sub(/tempID="[0-9]+"/,"tempID=\"'"$id"'\""); matches++ }
{ print $0 }' filName.py >filName.py.changed # ^^ here ^^
Erklärung. Ihr ursprünglicher Befehl lautet wie folgt
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 ^^^
Und dies ist der verbesserte Befehl:
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 ^^^
Um die Anführungszeichen-Hektik zu reduzieren, können Sie -v
die Option verwenden, um die Variable an zu übergeben awk
. Dann müssen Sie einfache Anführungszeichen nicht mitten in der Sequenz schließen und wieder öffnen, nur um die Shell erweitern zu lassen $id
. Stattdessen wird nicht zitiertes (wie awk
es aussieht) von selbst id
erweitert . Doppelte Anführungszeichen, die wir hinzufügen müssen, sollten wie zuvor maskiert werden:awk
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
Antwort2
Um Ihr Ziel zu erreichen, müssen Sie:
Für doppelte Anführungszeichen:
- AWK: Setzen Sie doppelte Anführungszeichen
"
in andere doppelte Anführungszeichen.
$1 $2
=>foobar
$1" __"$2"__"
=>foo __bar__
$1" \""$2"\""
=>foo "bar"
Für einfache Anführungszeichen:
Shell: Beenden Sie
'…'
Ihr gesamtes Awk-Skript und verwenden Sie einen anderen Satz'…'
darin.
'escaped 'unescaped' escaped'
'$LINUX '$OSTYPE' $CPUTYPE'
=>$LINUX linux-gnu $CPUTYPE
Shell: Escape,
'
wenn Sie wörtlich gedruckt werden möchten.
'apostrophe that'\''s literal'
=>apostrophe that's literal
Zum Beispiel
echo foo bar | awk '{print "\""$1"\" '\''"$2"'\''"}'
"foo" 'bar'