目前,我正在使用 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 ^^^
為了減少引用狂熱,您可以使用-v
option 將變數傳遞給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'