我有一个文件,其中的行由内部回车符分隔,如下所示:
电磁脉冲|123|10\r信息|约翰|史密斯|M|1980/01/12\r地址|125|布里奇路|哥伦布|俄亥俄州 电磁脉冲|456|10\r信息|大卫|皮尔特|M|1980/02/12\r地址|257|布里奇路|哥伦布|俄亥俄州 电磁脉冲|789|10\r信息|珍|麦肯齐|F|1980/03/12\r地址|389|布里奇路|哥伦布|俄亥俄州
请注意,CR 之间的行部分进一步由|
字符分隔。
我想在 CR 字符处将每一行分成单独的行。然后每个新的行(即,用换行符替换 CR 形成的行)应以|
原始行的 Id(第二个分隔字段)开头。
预期输出:
EMP|123|10
123|INFO|JOHN|SMITH|M|01/12/1980
123|ADDR|125|BRIDGE RD|COLUMBUS|OH
EMP|456|10
456|INFO|DAVID|PIRT|M|02/12/1980
456|ADDR|257|BRIDGE RD|COLUMBUS|OH
EMP|789|10
789|INFO|JENN|MCKENZI|F|03/12/1980
789|ADDR|389|BRIDGE RD|COLUMBUS|OH
Id 是重复的,因此我们可以知道输出中的每组三行属于同一(一个)输入行。
我尝试了下面的命令,但它只用换行符替换了 CR;我不知道如何将 Id 附加到新行
tr '\r' '\n' < test.txt > new.txt
输出:
EMP|123|10
INFO|JOHN|SMITH|M|01/12/1980
ADDR|125|BRIDGE RD|COLUMBUS|OH
EMP|456|10
INFO|DAVID|PIRT|M|02/12/1980
ADDR|257|BRIDGE RD|COLUMBUS|OH
EMP|789|10
INFO|JENN|MCKENZI|F|03/12/1980
ADDR|389|BRIDGE RD|COLUMBUS|OH
我怎样才能做到这一点?
答案1
怎么样
$ awk -F '\r' '{
print $1;
split($1,a,"|");
for(i=2;i<=NF;i++) print a[2] "|" $i;
}' file
EMP|123|10
123|INFO|JOHN|SMITH|M|01/12/1980
123|ADDR|125|BRIDGE RD|COLUMBUS|OH
EMP|456|10
456|INFO|DAVID|PIRT|M|02/12/1980
456|ADDR|257|BRIDGE RD|COLUMBUS|OH
EMP|789|10
789|INFO|JENN|MCKENZI|F|03/12/1980
789|ADDR|389|BRIDGE RD|COLUMBUS|OH
答案2
在 sed 中:
sed ':loop; s/^\([^|]*|\)\([^|]*|\)\([^\r]*\)\r/\1\2\3\n\2/; t loop'
这是一个(某种程度上)简单的替换:匹配由所有字符组成的模式(即,直到并包括)\r
缓冲区中的第一个字符。将其分为三个捕获组:
- 一切都经过(即,直到并包括)
|
缓冲区中的第一个。这将适用EMP|
于文件中的每一行。 - 之后的所有内容,直到(即,直到并包括)
|
缓冲区中的下一个(即,第二个)。这将是123|
,456|
或789|
在您的文件中。 - 之后的一切,直到(但是不是
\r
包括)缓冲区中的第一个。
然后将上面的替换为
- 三个捕获组 (
\1\2\3
);即,直到(但不包括)\r
缓冲区中第一个的所有内容, - 换行符,以及
- 第二个捕获组 (
\2
);即 id 和|
.
然后缓冲区的其余部分(所有内容后\r
缓冲区中的第一个)保留在原处,因此它位于新创建的行上的重复 id 之后。
那么,如果上面匹配并且s替换成功(t
是测试如果成功则转到),返回并重试。
对于初学者来说可能不明显的一个方面是,即使我们\n
使用 substitute 命令,从而创建一个新行,
sed
仍然对整个缓冲区进行操作(包括内部/嵌入的换行符)而不仅仅是“新行”(即换行符之后的部分)。所以, sed
读第一行,
EMP|123|10\rINFO|JOHN|SMITH|M|01/12/1980\rADDR|125|BRIDGE RD|COLUMBUS|OH
进入缓冲区。该s
命令第一次执行后,缓冲包含
EMP|123|10
123|INFO|JOHN|SMITH|M|01/12/1980\rADDR|125|BRIDGE RD|COLUMBUS|OH
所以s
命令的下一次迭代匹配
\1
=EMP|
,\2
=123|
,并且\3
=10 123|INFO|JOHN|SMITH|M|01/12/1980
(包括在第一次迭代中插入的换行符)。
警告:如果输入行中的\r
第二个前面有一个,这可能会造成混乱 。|