将文本标记从一行插入到下一行的特定位置

将文本标记从一行插入到下一行的特定位置

我有一个包含文本数据的文件,需要将其转换为 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模式:将Next 行附加到缓冲区,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

相关内容