[英]Replace sql column with awk
我在替換SQL腳本中的列時遇到問題。
我有這樣的數據(test.sql):
INSERT INTO TABLE
(ID,TEXT)
VALUES
(1,'TEXT');
INSERT INTO TABLE
(ID,TEXT)
VALUES
(2,'TEXT242');
INSERT INTO TABLE
(ID,TEXT)
VALUES
(3,'TEXT424242');
我想用新值替換ID列上的“ TEXT”。 可以,我可以這樣做:
NEW="NEW"
grep 3 test.sql | awk -F "," -v OFS=, '{$2'$index'="'"'${NEW}'"'"; print }'
它將打印:
(3,'NEW');
所以,我有兩個問題:
我希望看到包括新行在內的所有行都進行如下更改:
INSERT INTO TABLE (ID,TEXT) VALUES (1,'TEXT'); INSERT INTO TABLE (ID,TEXT) VALUES (2,'TEXT242'); INSERT INTO TABLE (ID,TEXT) VALUES (3,'NEW');
我想有一個完全匹配:所以3只有3而不是30 33 ...
可以這樣做,但是假設要替換的數據中沒有任何撇號,並且要匹配的id后面緊跟着一個逗號:
awk -F"'" -v id=3 -v newval="${NEW}" 'NF==3 { print $1 FS ($1 ~ id",$" ? newval:$2) FS $3 } NF!=3 {print $0}' test.sql
細分:
awk -F"'" -v id=3 -v newval="${NEW}" '
使用'
作為分隔符,設置vars id和newval,其中newval來自bash
NF==3 { print $1 FS ($1 ~ id",$" ? newval:$2) FS $3 }
當有3個字段時,如果id匹配,則打印出現有的第二個字段或newval。
NF!=3 {print $0}' test.sql
打印所有其他行而不進行調整。
當NEW="JIVE"
輸出以下內容時:
INSERT INTO TABLE
(ID,TEXT)
VALUES
(30,'TEXT');
INSERT INTO TABLE
(ID,TEXT)
VALUES
(33,'TEXT242');
INSERT INTO TABLE
(ID,TEXT)
VALUES
(3,'JIVE');
在這里,我用30和33替換了原始ID 1和2,以證明它只是在修改您想要的行。
好吧,這變得更丑陋了,但這是一個新的“一個班輪”:
awk -F"'" -v id=3 -v newval="${NEW}" -v ind=$INDEX 'NF >= 2 {for(i=1;i<=NF;i++) {fld=($1 ~ id",$" && i==ind) ? newval : $i; printf("%s%s", fld, (i==NF ? "\n" : FS) ) }} NF < 2{print}' test.sql
細分:
awk -F"'" -v id=3 -v newval="${NEW}" -v ind=$INDEX '
除了其他變量之外,還添加了一個ind變量( index
是保留的函數名)。 請注意,該指數是基於'
字段分隔符。 在您的評論中, $index
應該為6。
NF >= 2 {for(i=1;i<=NF;i++) {
超過兩個時,循環遍歷所有字段。
fld=($1 ~ id",$" && i==ind) ? newval : $i;
根據ID和字段索引的匹配設置輸出字段。
printf("%s%s", fld, (i==NF ? "\n" : FS) ) }}
打印出當前的字段和字段分隔符,將最后一個更改為換行符。
NF < 2{print}' test.sql
打印出所有剩余的行。
如果您只需要解決此特定問題(不需要完全解析語句,而且格式無變化),則sed
可以實現一個更簡單的解決方案 :
更新 :OP已澄清它是第8列,應替換其值。
# Specify ID to match and replacement text.
id=3 new="NEW"
# Let `sed` perform the substitution.
# `sed` outputs ALL lines by default, whether a substitution took place or not.
sed -E \
"s/\($id(,[^,]+,[^,]+,[^,]+,[^,]+,[^,]+,[^,]+),[^,]+(.*)/($id\1,'$new'\2/" \
test.sql
如您所見,[^,]+
為了捕獲中間的列值,[^,]+
在(...)
中重復了6次-遺憾的是,使用{6}
重復6次是不可行的,因為那樣只會捕獲模式的最后一個實例。
基於字段的awk
解決方案:
更新 :OP已澄清它是第8列,應替換其值。
這種更靈活的解決方案使您也可以傳入目標列的從1開始的索引。 但是,假設ID列始終是first 。
awk -F '[,()]' -v id=3 -v ndx=8 -v new="'NEW'" '
$2==id {
$(ndx+1)=new # replace the column value
# Row has been rebuilt with just spaces as separators
# output it in the original format.
printf " (%s", id
for (i=3;i<NF;++i) printf ",%s", $i
print ");"
next
}
{ print }
' test.sql
請注意,不保留確切的前導空格。
另外請注意,由於輸入線路用字段分隔符開始 ( (
), awk
在開始創建一個額外的,空場;因此,指數加1。
重申一下警告:通常, awk
和sed
都不是解析SQL [DML]語句的正確工具。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.