代码之家  ›  专栏  ›  技术社区  ›  kal

将多行合并为一行

  •  8
  • kal  · 技术社区  · 15 年前

    我有一个输入为

    Input:
    <abc a="1">
       <val>0.25</val>
    </abc> 
    <abc a="2">
        <val>0.25</val>
    </abc> 
    <abc a="3">
       <val>0.35</val>
    </abc> 
     ...
    
    Output:
    <abc a="1"><val>0.25</val></abc> 
    <abc a="2"><val>0.25</val></abc>
    <abc a="3"><val>0.35</val></abc>
    

    我在一个输入格式的文件中有大约20万行,如何快速地将其转换为输出格式。

    11 回复  |  直到 15 年前
        1
  •  5
  •   Dave Kirby    11 年前

    在vim里你可以用

    :g/<abc/ .,/<\/abc/ join!
    

    通常情况下:join会在每行末尾添加一个空格,但 ! 抑制它。

    一般来说,我建议使用Python、Ruby或Perl等语言中适当的XML解析库来处理XML文件(我建议使用Python+ElementTree),但在这种情况下,使用regex解决方案就足够简单了。

        2
  •  4
  •   Matteo Riva    15 年前

    在Vim中:

    • qq
    • gJgJ :连接下两行而不添加空格
    • j :向下
    • q :停止录制
    • N@q :N=行数(实际上大约是所有行的1/3,因为它们在运行中被压缩)
        3
  •  1
  •   glenn jackman    15 年前
    $ awk '
        /<abc/ && NR > 1 {print ""}
        {gsub(" +"," "); printf "%s",$0}
    ' file
    <abc a="1"> <val>0.25</val></abc>
    <abc a="2"> <val>0.25</val></abc>
    <abc a="3"> <val>0.35</val></abc>
    
        4
  •  1
  •   pazhitnov    15 年前

    while read s; do echo -n $s; read s; echo -n $s; read s; echo $s; done < file.xml
    
        5
  •  1
  •   Neg_EV    15 年前

    可以录制宏。基本上,我要做的是从光标在第一行的开始处开始。按“qa”(将宏记录到a寄存器)。按下shift-V键可切换为逐行显示模式。然后搜索结束标记“//abc”。然后按shift-J键连接管路。然后您必须将光标移动到下一个标记,可能是使用“j^”,然后按“q”停止录制。然后可以使用'@a'重新运行录制或指定10000@a如果你愿意的话。如果标签不一样或者不在后面,你只需要改变你找到开始和结束标签的方式来搜索或者类似的东西。

        6
  •  1
  •   SergioAraujo    15 年前
    sed '/^<abc/{N;N;s/\n\| //g}'
    
    # remove \n or "space" 
    # Result
    
    <abca="1"><val>0.25</val></abc>
    <abca="2"><val>0.25</val></abc>
    <abca="3"><val>0.35</val></abc>
    
        7
  •  0
  •   zellio    15 年前

    不雅观的perl一行就应该做到这一点,尽管不是特别快。

    cat file | perl -e '
        $x=0;
        while(<>){
            s/^\s*(\S*(?:\s+\S+)*)\s*$/$1/g;
            print;
            $x++;
        if($x==3){
            print"\n";
            $x=0;
        }
    }' > output
    
        8
  •  0
  •   codaddict    15 年前

    您可以这样做:

    perl -e '$i=1; while(<>){chomp;$s.=$_;if($i%3==0){$s=~s{>\s+<}{><};print "$s\n";$s="";}$i++;}' file
    
        9
  •  0
  •   ghostdog74    15 年前
    sed '/<abc/,/<\/abc>/{:a;N;s/\n//g;s|<\/abc>|<\/abc>\n|g;H;ta}'  file
    
        10
  •  0
  •   ghostdog74    15 年前
    tr "\n" " "<myfile|sed 's|<\/abc>|<\/abc>\n|g;s/[ \t]*<abc/<abc/g;s/>[ \t]*</></g'
    
        11
  •  0
  •   user301075 user301075    15 年前

    :%s/\(^<abc.*>\)^M^\(.*\)^M^\(^<\/abc>\).*^M/\1\2\3^M/g

    我应该有额外的空格(或者在值之间有一个制表符),但是您可以根据它是什么来删除它(\t或\\\\)。

    您正在搜索/替换的是(pattern1)[enter](pattern2)[enter](pattern3)[enter],并将其替换为(pattern1)(pattern2)(pattern3)[enter]

    ^M是用ctrl+v ctrl+M完成的