【问题标题】:Convert lines with sublines into single lines将带有子线的行转换为单行
【发布时间】:2017-10-06 06:31:45
【问题描述】:

我有一个需要导入 SQL 数据库的大量文本文件。 问题是该文件每条记录包含几行,所以我需要每条记录单行。

文本文件现在看起来像这样;

L;1;100;Product1;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;
T;TEXT2;177
T;TEXT;130
T;TEXT;156x55
O;2;40448652267;43242;
O;3;0481439;344;
L;1;100;Product2;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;
T;TEXT2;177
T;TEXT;130
T;TEXT;156x55
O;2;40448652267;43242;
O;3;0481439;344;
L;1;100;Product2;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;
T;TEXT2;177
T;TEXT;130
T;TEXT;156x55
O;2;40448652267;43242;
O;3;0481439;344;
L;1;100;Product3;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;
T;TEXT2;177
T;TEXT;130
T;TEXT;156x55
O;2;40448652267;43242;
O;3;0481439;344;
L;1;100;Product4;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;
T;TEXT2;177
T;TEXT;130
T;TEXT;156x55
O;2;40448652267;43242;
O;3;0481439;344;

我需要它以这样的方式结束,以便将其导入 SQL 数据库;

是否有任何 SED 命令可用于此转换,还是更好的方法?

L;1;100;Product1;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;TEXT2;177;TEXT;130;TEXT;156x55;2;40448652267;43242;;3;0481439;344;
L;1;100;Product2;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;TEXT2;177;TEXT;130;TEXT;156x55;2;40448652267;43242;;3;0481439;344;
L;1;100;Product3;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;TEXT2;177;TEXT;130;TEXT;156x55;2;40448652267;43242;;3;0481439;344;
L;1;100;Product4;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;TEXT2;177;TEXT;130;TEXT;156x55;2;40448652267;43242;;3;0481439;344;

感谢所有有关如何以最佳方式将此数据导入 mySQL 数据库的提示 :)

【问题讨论】:

  • 用 sed 可能可行,但更适合 awk...
  • 欢迎栈溢出,感谢使用代码标签。请检查我的 awk 代码一次,如果这对您有帮助,请告诉我。
  • 除了添加您尝试过的内容之外,您还应该添加转换的详细信息 - 例如从非L;行中删除第一个字段
  • 根据您的输出 - 如果有其他要求,您应该提到:是否真的应该删除 T;O;。更新您的问题以使其更清晰

标签: mysql linux awk sed


【解决方案1】:

awk单行:

awk '{printf("%s", /^L/ ? (p?RS:"") $0:substr($0, index($0,";")+1 ));p=1}END{print ""}' infile

OR(冗长)

awk '/^L/{ if(p)print ""; printf("%s",$0);next}{ printf("%s",substr($0,index($0,";")+1));p=1}END{print ""}' infile

更好的可读性:

awk '/^L/{ 
           if(p)print ""; 
           printf("%s",$0);
           next
         }
         { 
           printf("%s",substr($0,index($0,";")+1));
           p=1
         }
      END{
           print ""
         }
    ' infile

输入:

$ cat infile
L;1;100;Product1;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;
T;TEXT2;177
T;TEXT;130
T;TEXT;156x55
O;2;40448652267;43242;
O;3;0481439;344;
L;1;100;Product2;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;
T;TEXT2;177
T;TEXT;130
T;TEXT;156x55
O;2;40448652267;43242;
O;3;0481439;344;
L;1;100;Product2;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;
T;TEXT2;177
T;TEXT;130
T;TEXT;156x55
O;2;40448652267;43242;
O;3;0481439;344;
L;1;100;Product3;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;
T;TEXT2;177
T;TEXT;130
T;TEXT;156x55
O;2;40448652267;43242;
O;3;0481439;344;
L;1;100;Product4;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;
T;TEXT2;177
T;TEXT;130
T;TEXT;156x55
O;2;40448652267;43242;
O;3;0481439;344;

输出:

$ awk '{printf("%s", /^L/ ? (p?RS:"") $0:substr($0, index($0,";")+1 ));p=1}END{print ""}' infile
L;1;100;Product1;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;TEXT2;177TEXT;130TEXT;156x552;40448652267;43242;3;0481439;344;
L;1;100;Product2;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;TEXT2;177TEXT;130TEXT;156x552;40448652267;43242;3;0481439;344;
L;1;100;Product2;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;TEXT2;177TEXT;130TEXT;156x552;40448652267;43242;3;0481439;344;
L;1;100;Product3;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;TEXT2;177TEXT;130TEXT;156x552;40448652267;43242;3;0481439;344;
L;1;100;Product4;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;TEXT2;177TEXT;130TEXT;156x552;40448652267;43242;3;0481439;344;

【讨论】:

  • 谢谢!这几乎符合我的需要,在原始文件中,我在每一行之后都有 [CR] 和 [LF] 换行符。当我运行 sctipt 时,我仍然有 [CR] 换行符。无论如何我也可以删除它?
  • @Andreas 你也可以添加其他样本吗?
  • 我在这里上传了示例的截图,因为在这篇文章中很难显示字符:) dropbox.com/s/g72kg00ouz0fxa5/line.png
  • 还有一个问题.. 在 TEXT2;177 之后它缺少一个 ;知道我怎么能得到它吗?
【解决方案2】:

awk 保存:

awk '{printf("%s%s",NR==1 && $0 ~ /^L;/?"":($0 ~ /^L;/?RS:""),$0)} END{print ""}'  Input_file

输出如下。

L;1;100;Product1;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;T;TEXT2;177T;TEXT;130T;TEXT;156x55O;2;40448652267;43242;O;3;0481439;344;
L;1;100;Product2;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;T;TEXT2;177T;TEXT;130T;TEXT;156x55O;2;40448652267;43242;O;3;0481439;344;
L;1;100;Product2;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;T;TEXT2;177T;TEXT;130T;TEXT;156x55O;2;40448652267;43242;O;3;0481439;344;
L;1;100;Product3;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;T;TEXT2;177T;TEXT;130T;TEXT;156x55O;2;40448652267;43242;O;3;0481439;344;
L;1;100;Product4;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;T;TEXT2;177T;TEXT;130T;TEXT;156x55O;2;40448652267;43242;O;3;0481439;344;

说明:也添加说明和非单行形式的解决方案。

awk '{
printf("%s%s",NR==1 && $0 ~ /^L;/?"":($0 ~ /^L;/?RS:""),$0) ##Using printf here to print the lines. %s%s to print the lines, So while printing them mentioning 2 conditions here NR==1(where it checks if line is very first line of Input_file and line starts from L; then print NULL else if a line starts from L; then print RS(whose default value is new line) else print NULL value. For second string simple print current line.
}                                                           ##So idea behind this logic is simple to print a new line which starts from L; apart from first line, so that we could get output as per OP.
END{
print ""                                                    ##In the END block to print a new line simple printing NULL so that a new line will be inserted.
}
' Input_file                                                ##Mentioning the Input_file here.

【讨论】:

    【解决方案3】:

    这是sed 解决方案,

    sed ':a;/O;3/!{N;s/\n//;ba}' file
    

    简要说明,

    • 目标是删除除以“O;3”开头的行之外的所有“\n”。
    • :a:在脚本开头设置标签'a'
    • /O;3/!{N;s/\n//;ba}:如果行不以 "O;3" 开头,则追加下一行并删除 '\n'。然后我们回到标签“a”来处理以下行。

    【讨论】:

      【解决方案4】:

      Awk解决方案:

      awk -v ORS= 'NR>1 && /^L/{print "\n"}/^T/{sub(/.;/,";")}END{ print "\n" }1' file
      

      输出:

      L;1;100;Product1;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;;TEXT2;177;TEXT;130;TEXT;156x55O;2;40448652267;43242;O;3;0481439;344;
      L;1;100;Product2;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;;TEXT2;177;TEXT;130;TEXT;156x55O;2;40448652267;43242;O;3;0481439;344;
      L;1;100;Product2;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;;TEXT2;177;TEXT;130;TEXT;156x55O;2;40448652267;43242;O;3;0481439;344;
      L;1;100;Product3;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;;TEXT2;177;TEXT;130;TEXT;156x55O;2;40448652267;43242;O;3;0481439;344;
      L;1;100;Product4;Text;2;Text2;;20171006;;;1;;76;;;U;1000;;;TEXT2;177;TEXT;130;TEXT;156x55O;2;40448652267;43242;O;3;0481439;344;
      

      【讨论】:

      • 您可能看错了,需要更多更改1000;;T;,T 不应该来
      • @AkshayHegde,OP 没有提到删除 T;。如果您保证它是必需的 - 请参阅我的更新
      • 是的,按照预期的 o/p 看起来是这样的
      【解决方案5】:

      你也可以试试这个

      while read l;do [ "${l%%;*}" = 'L' ]&&{ [ $n ] &&echo "${n%;}";n="$l";}||n="$n${l#*;};";done<infile;echo "${n%;}"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-19
        • 1970-01-01
        • 1970-01-01
        • 2019-04-30
        相关资源
        最近更新 更多