我有一个包含文本数据的文件,需要将其转换为 SQL 语句。
@Parse ABC
// This is a comment
//-----
"f2"
f4-1
$f5f5f5f5 0000
f4-2
$f5f5f5f5 0001
$f5f5f5f5 0002
f4-3
$f5f5f5f5 0003
$f5f5f5f5 0004
f4-4
$f5f5f5f5 0005
$f5f5f5f5 0006
f4-5
$f5f5f5f5 0007
$f5f5f5f5 0008
$f5f5f5f5 0009
$f5f5f5f5 0010
$f5f5f5f5 0011
$f5f5f5f5 0012
//========
"This is f2 but is different from the previous f2"
f4-6
$f5f5f5f5 0013
f4-7
$f5f5f5f5 0014
$f5f5f5f5 0015
f4-8
$f5f5f5f5 0016
$f5f5f5f5 0017
f4-9
$f5f5f5f5 0018
$f5f5f5f5 0019
f4-10
$f5f5f5f5 0020
$f5f5f5f5 0021
$f5f5f5f5 0022
$f5f5f5f5 0023
$f5f5f5f5 0024
$f5f5f5f5 0025
//========
最初该文件看起来如上所示。
我希望这个文件看起来像这样
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "f2-1", "", "f4-1", "$f5f5f5f5 0000");
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "f2-1", "", "f4-2", "$f5f5f5f5 0001<TAB>$f5f5f5f5 0002");
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "f2-1", "", "f4-3", "$f5f5f5f5 0003<TAB>$f5f5f5f5 0004");
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "f2-1", "", "f4-4", "$f5f5f5f5 0005<TAB>$f5f5f5f5 0006");
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "f2-1", "", "f4-5", "$f5f5f5f5 0007<TAB>$f5f5f5f5 0008<TAB>$f5f5f5f5 0009<TAB>$f5f5f5f5 0010<TAB>$f5f5f5f5 0011<TAB>$f5f5f5f5 0012");
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "This is f2-2 but is different from the previous f2-1", "", "f4-6", "$f5f5f5f5 0013");
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "This is f2-2 but is different from the previous f2-1", "", "f4-7", "$f5f5f5f5 0014<TAB>$f5f5f5f5 0015");
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "This is f2-2 but is different from the previous f2-1", "", "f4-8", "$f5f5f5f5 0016<TAB>$f5f5f5f5 0017");
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "This is f2-2 but is different from the previous f2-1", "", "f4-9", "$f5f5f5f5 0018<TAB>$f5f5f5f5 0019");
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "This is f2-2 but is different from the previous f2-1", "", "f4-10", "$f5f5f5f5 0020<TAB>$f5f5f5f5 0021<TAB>$f5f5f5f5 0022<TAB>$f5f5f5f5 0023<TAB>$f5f5f5f5 0024<TAB>$f5f5f5f5 0025");
我使用下面的命令将原始文件更改为当前的输出,下面的命令中使用的所有文件都有 dos 行结尾。
sed -e 's/[[:space:]]$//' -e 's/^[[:alnum:]*()].*/INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "", "", "&", "");/' /path/to/files/* > '/path/to/file.sql';
当前“file.sql”中的数据如下:
@Parse ABC
// This is a comment
//-----
"f2"
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "", "", "f4-1", "");
$f5f5f5f5 0000
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "", "", "f4-2", "");
$f5f5f5f5 0001
$f5f5f5f5 0002
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "", "", "f4-3", "");
$f5f5f5f5 0003
$f5f5f5f5 0004
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "", "", "f4-4", "");
$f5f5f5f5 0005
$f5f5f5f5 0006
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "", "", "f4-5", "");
$f5f5f5f5 0007
$f5f5f5f5 0008
$f5f5f5f5 0009
$f5f5f5f5 0010
$f5f5f5f5 0011
$f5f5f5f5 0012
//========
"This is f2 but is different from the previous f2"
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "", "", "f4-6", "");
$f5f5f5f5 0013
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "", "", "f4-7", "");
$f5f5f5f5 0014
$f5f5f5f5 0015
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "", "", "f4-8", "");
$f5f5f5f5 0016
$f5f5f5f5 0017
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "", "", "f4-9", "");
$f5f5f5f5 0018
$f5f5f5f5 0019
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "", "", "f4-10", "");
$f5f5f5f5 0020
$f5f5f5f5 0021
$f5f5f5f5 0022
$f5f5f5f5 0023
$f5f5f5f5 0024
$f5f5f5f5 0025
//========
我想将上面的数据更改为以下内容:
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "", "", "f4-1", "");
INSERT INTO `` (`f1`, `f2`, `f3`, `f4`, `f5`) VALUES (NULL, "", "", "f4-2", "$f5f5f5f5 0000");
包含数据的文件具有 dos 行结尾。
sed -r "s/\", \"\"\);\r\n(.*)\r\nINSERT INTO/\", \"\1\");\r\nINSERT INTO/" /path/to/file.sql;
上面的命令运行时没有错误,但命令的输出与输入相同。
我最初确实尝试开始sed -e
工作,但这给了我无法修复的错误,这些错误大多是逃避sed -r
已修复的角色问题。
我刚刚尝试仅替换行结尾,例如替换\r\n
为----
。但他们没有被替换,所以我认为这就是我的问题所在。
所以我后来发现了sed
在线工作,我没有意识到这一点,所以这不一定必须在 sed 中完成,尽管我不知道我会用什么来代替,如果有人想建议的话我很乐意自己尝试一下,如果遇到问题,可以再次发帖。
答案1
笔记自发布此答案以来,示例输入/所需输出发生了巨大变化,因此它可能无法解决现在的问题。
以下解决方案假设
- 要插入的值是该行中唯一的字符串标记
- 插入值的地方就是
"");
模式
在这种情况下,以下awk
程序应该有效:
awk 'index($0,"INSERT")==1 && buf {sub(/"");/, "\"" buf "\");"); buf=""}
NF==1{buf=$1;next} 1' input.txt
其工作原理如下:
- 如果该行以 开头,并且填充了
INSERT
缓冲区变量,则它将用 替换该模式,后跟 的内容,最后是。然后该变量被清除。buf
"");
"
buf
");
buf
- 如果该行只有一个字段,则假定这是包含要填充下一行的值的行,然后将其放入变量中
buf
(但否则处理会立即跳到下一行)。 - 看似偏离
1
规则块之外的内容{ ... }
指示awk
打印当前行,包括所做的所有修改。
如果一行之前有多个“值”行INSERT
,则它将采用最后一个“值”行的内容。空行将被忽略(但仍会出现在输出中)。包含多个不以 开头的“单词”的行INSERT
也将按原样打印。
请注意,awk
默认情况下不会对文件执行就地编辑(就像 一样sed
),因此您需要将输出重定向到文件中并稍后覆盖原始输入,或者(如果您有一个相当新的 GNU Awk),使用-i inplace
执行就地编辑的扩展。
建议dos2unix
在处理之前运行原始文件,将 DOS 行结尾替换为 Unix 风格。unix2dos
如果修改后的文件中需要 DOS 行结尾,则可以稍后运行 。
答案2
要处理sed
成对的行,可以使用以下N;P;D
模式:将N
ext 行附加到缓冲区,P
仅打印缓冲区中的第一行,然后D
删除第一行以继续执行脚本,而第二行仍在缓冲区中。
在你的情况下,这会导致
sed 'N;s/", "");\r\n\($[^ ]*\).*/", "\1");/;P;D' /path/to/file
现在我不确定如果有额外的行你想做什么。也许只是摆脱它们:
sed '/^$/d;N;s/", "");\r\n\($[^ ]*\).*/", "\1");/;P;D' /path/to/file