我在替换 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...
最佳答案
如果您只需要解决这个特定问题(不需要完全解析语句并且格式没有变化),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 列总是第一个。
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] 语句的正确工具。
关于linux - 用 awk 替换 sql 列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23111971/