Text-Processing

如何將 CR 分隔的字元串拆分為多行並將 id 附加到每個新行?

  • June 11, 2019

我有一個文件,其中的行由內部輸入符分區,如下所示:

EMP|123|10 **\r**資訊|約翰|史密斯|M|01/12/1980 **\r**地址|125|BRIDGE RD|哥倫布|OH
EMP|456|10 **\r**資訊|大衛|PIRT|M|02/12/1980 **\r**地址|257|BRIDGE RD|哥倫布|OH
EMP|789|10 **\r**資訊|JENN|MCKENZI|F|03/12/1980 **\r**地址|389|BRIDGE RD|哥倫布|OH

請注意,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

我怎樣才能做到這一點?

怎麼樣

$ 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

在 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 之後。

然後,如果上面的 match 和ssubstitute成功(tis test and goto if success),回去再試一次。

對初學者來說可能不明顯的一個方面是,即使我們使用s替換命令 將換行符\n插入緩衝區 ,從而創建了一個新行,仍然在整個緩衝區上執行(包括內部/嵌入的換行符)字元)而不僅僅是“換行符”(即換行符之後的部分)。所以, 讀第一行,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的第二個之前有 a,這可能會造成混亂 。|

引用自:https://unix.stackexchange.com/questions/524106