當我使用 AWK 來尋找和替換時,如何才能顯示引號?

當我使用 AWK 來尋找和替換時,如何才能顯示引號?

目前,我正在使用 AWK 來尋找並替換字串前三個出現的部分。該字串的格式如下,檔案中有很多這樣的字串:

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

使用這個連結,我找到了一種使用 AWK 查找並替換字串的前三個實例的方法。我將其更改為我需要它執行的操作,我的腳本片段如下:

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

上述程式碼的目標是匹配包含 tempID 的任何行,並將指派給 tempID 的數字替換為名為 的變數中儲存的值$id。尋找和替換效果很好,但我似乎遇到的一個問題是,無論我如何構造它,輸出都會列印不帶引號的 $id 。我嘗試轉義引號並添加單勾,但無論如何該行都更改為:

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

我嘗試刪除替換部分周圍的雙引號並將其構造為tempID="$id",但不幸的是這只是將 ID 號碼替換為字串$id

請告訴我是否有辦法查找和替換 tempID 值並用引號將該值引起來。我不堅持使用 AWK,因此使用任何其他實用程式(例如 sed)的任何其他方法也可以正常工作。

答案1

在您的命令中,有由 shell 解釋和刪除的引號,有由 解釋和刪除的引號awk,那麼您需要能夠保留下來的引號。你應該逃避他們:

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

解釋。你原來的命令是這樣的

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

這是改進後的命令:

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

為了減少引用狂熱,您可以使用-voption 將變數傳遞給awk.然後,您不需要在序列中間關閉並重新開啟單引號,只是為了讓 shell 展開$id。相反,未引用的(如awk所見)id是透過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

答案2

為了實現您想做的事情,您需要:

對於雙引號:

  • "AWK:在其他雙引號內轉義雙引號。
    $1 $2=> foobar
    $1" __"$2"__"=> foo __bar__
    $1" \""$2"\""=>foo "bar"

對於單引號:

  • Shell:退出你的整個awk腳本,在裡面'…'使用另一組。 =>'…'
    'escaped 'unescaped' escaped'
    '$LINUX '$OSTYPE' $CPUTYPE'$LINUX linux-gnu $CPUTYPE

  • Shell:轉義'你想按字面意思列印。
    'apostrophe that'\''s literal'=>apostrophe that's literal

例如

echo foo bar | awk '{print "\""$1"\" '\''"$2"'\''"}'
"foo" 'bar'

相關內容