【问题标题】:Merge 2 lines into one将 2 行合并为 1
【发布时间】:2012-06-26 08:01:38
【问题描述】:

我有一个以 9 位大学代码开头并以 5 位课程代码结尾的文本文件。

512161000 EN5121 K. K. Jorge Institute of Engineering Education and Research, Nashik 61220 Mechanical Engineering [Second Shift] XOPENH 1 116 16978
517261123 EN5172 R. C. Rustom Institute of Technology, Shirpur 61220 Mechanical Engineering [Second Shift] YOPENH 1 100 29555
617561234 EN6175 abc xyz Education Trust, abc xyz College of Engineering,
Pune 61220 Mechanical Engineering [Second Shift] ZOPENH 2 105 25017

如上面的 3 示例所示,有些条目有换行符。 我需要将第 3 行和第 4 行合并为一个,就像第 1 行和第 2 行一样,以便我可以轻松使用 grep、awk 等命令。

更新:

Kevin 的回答似乎不起作用。

cat todel.txt
112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of,
Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531

cat todel.txt | perl -ne 'chomp; if (/^\d{9}/) { print "\n$_" } else { print "$_\n" }' 
Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531ege of,

【问题讨论】:

  • awk '/^[0-9]/,/[0-9]$/' # 不起作用

标签: perl sed awk grep


【解决方案1】:

也许尝试删除逗号后出现的所有换行符,如下所示:

perl -i -pe 's/,\n/,/g' file.txt

也许您想在逗号后留出空格:

perl -i -pe 's/(,\s*)\n/$1/g' file.txt

【讨论】:

  • 逗号后不需要换行。
【解决方案2】:

假设您的数据在“file.txt”中,下面是一个扫描,可以将这些行重新组合在一起:

cat file.txt | perl -ne 'chomp; if (/^\d{9}/) { print "\n$_" } else { print "$_\n" }'

这假定所有有效记录都以 9 位数字开头。 “chomp”最初会删除换行符,模式决定换行符应该出现在输出中的什么位置。

【讨论】:

    【解决方案3】:

    关于拆分行:此sed 脚本假定前导数字后至少有一个空格(拆分的第一行),尾随数字前至少有一个空格(拆分的最后一行) ,并且每条分割线只有一个分割线。

    修改为接受带有 Windows CRLF 换行符 *nix LF 的输入。但请注意,输出是 *nix \n

    sed -nr 's/\r?$// # allow for '\r\n' newlines
             /^([0-9]{9}) .* ([0-9]{5})$/{p;b}
             /^([0-9]{9}) /{h;b}
             / ([0-9]{5})$/{x;G; s/\n//; p}' 
    

    或者,更短,但可能不太可读:

    sed -nr 's/\r?$//; /^([0-9]{9}) /{/ ([0-9]{5})$/{p;b};h;b};/ ([0-9]{5})$/{x;G; s/\n//; p}' 
    

    我确实希望第一个更快,因为最频繁的测试(对于整行)只涉及一个正则表达式,而第二个(较短的)脚本需要两个正则表达式测试来进行最频繁的测试。

    这是我得到的输出;使用GNU sed 4.2.1

    512161000 EN5121 K. K. Jorge Institute of Engineering Education and Research, Nashik 61220 Mechanical Engineering [Second Shift] XOPENH 1 116 16978
    517261123 EN5172 R. C. Rustom Institute of Technology, Shirpur 61220 Mechanical Engineering [Second Shift] YOPENH 1 100 29555
    617561234 EN6175 abc xyz Education Trust, abc xyz College of Engineering,Pune 61220 enter code hereMechanical Engineering [Second Shift] ZOPENH 2 105 25017
    112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of,Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531
    

    【讨论】:

    • # 不适用于问题中显示的示例。 ## sed 4.1.5 版
    • 这很奇怪;它对我有用(我已经添加了输出和 sed 版本来回答)。它是否给出错误消息,或者只是不产生所需的输出? (也许它不能处理扩展的正则表达式 swithc -r ??)
    • 文件是否有正常的 *nix \n 换行符(与 Windows \r\n 或者甚至是旧的 Mac \r 相比)?我以前在处理 Windows 生成的文件时遇到过问题。
    • 好 :) 很容易适应 sed 来处理 \r... 我会修改脚本来处理它。那你喂它\n\r\n 都没关系
    【解决方案4】:

    这可能对你有用:

    sed ':a;$!N;/ [0-9]\{5\}\n[0-9]\{9\} /!s/\n//;ta;P;D' file
    

    解释:

    • 如果该行不是以空格结尾,后跟五位数字,后跟九位数字,然后是空格,请删除换行符。

    编辑:

    测试数据:

    cat <<\! >/tmp/codel.txt
    > 112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of,
    > Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531
    > !
    sed ':a;$!N;/\s[0-9]\{5\}\n[0-9]\{9\}\s/!s/\n//;ta;P;D' /tmp/codel.txt 
    112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of,Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531
    sed ':a;$!N;/\s[0-9]\{5\}\n[0-9]\{9\}\s/!s/\n//;ta;P;D' /tmp/{codel.txt,codel.txt,codel.txt} 
    112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of,Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531
    112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of,Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531
    112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of,Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531
    

    【讨论】:

    • 似乎不适用于上面的第二个示例。问题已更新。
    • @shantanuo 使用您的新数据进行了测试(请参阅编辑)对我来说似乎很好。
    【解决方案5】:

    试试这个

    sed '/^[0-9]\{9\}/{h;};/^[0-9]\{9\}/!{x;G;s/\n//g;}' test | grep -E '[0-9]{5}$'
    

    【讨论】:

    • 不适用于问题中显示的第一个示例文件。
    【解决方案6】:
    awk '! ($1 ~ /^[[:digit:]]/) {$0 = save " " $0} $1 ~ /^[[:digit:]]/ {save = $0} $NF ~ /[[:digit:]]$/ {print}' inputfile
    

    【讨论】:

    • @shantanuo:第一个是我测试过的,对我来说效果很好。此外,当我通过管道将其发送到 wc -l 时,我得到 3。
    • Awk 3.1.5 返回 4 行而不是 3
    【解决方案7】:
    cat todel.txt |awk 'BEGIN {i=0} {first[i]=$1; lines[i++] = $0;} END {for (x=0; x<i; x++) { if ( x==(i - 1) || (first[x + 1] ~ /^[0-9]+$/ && length(first[x + 1])==9) ) {printf("%s: %s\n", x, lines[x]);} else {printf("%s: %s%s\n", x, lines[x], lines[x + 1]); x++;} } }'
    

    【讨论】:

      【解决方案8】:

      这适用于包含的数据集,假设有效记录以五位数字结尾:

      use Modern::Perl;
      
      my $data = do{local $/; <DATA>};
      $data =~ s/([^\d]{5})\n/$1 /sg;
      say $data;
      
      
      __DATA__
      512161000 EN5121 K. K. Jorge Institute of Engineering Education and Research, Nashik 61220 Mechanical Engineering [Second Shift] XOPENH 1 116 16978
      517261123 EN5172 R. C. Rustom Institute of Technology, Shirpur 61220 Mechanical Engineering [Second Shift] YOPENH 1 100 29555
      617561234 EN6175 abc xyz Education Trust, abc xyz College of Engineering,
      Pune 61220 Mechanical Engineering [Second Shift] ZOPENH 2 105 25017
      112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of,
      Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 93531
      

      输出:

      512161000 EN5121 K. K. Jorge Institute of Engineering Education and Research, Nashik 61220 Mechanical Engineering [Second Shift] XOPENH 1 116 16978
      517261123 EN5172 R. C. Rustom Institute of Technology, Shirpur 61220 Mechanical Engineering [Second Shift] YOPENH 1 100 29555
      617561234 EN6175 abc xyz Education Trust, abc xyz College of Engineering, Pune 61220 Mechanical Engineering [Second Shift] ZOPENH 2 105 25017
      112724510 EN1127 Jagadambha Bahuuddeshiya Gramin Vikas Sanstha's Jagdambha College of, Engineering and Technology, Yavatmal 24510 Computer Engineering LSCO 1 55 935315
      

      【讨论】:

      • 你的正则表达式 s/([^\d]{5})\n/$1 /sg; 应该是 s/^(\d{9}.*?)(\n)[^\d{5}\n]/$1 /gm; 因为如果该行找到一个 行之间有 5 位数字的数字并且如果换行在那里(实际上就是这种情况) 那么你的正则表达式就会失败。例如:考虑在第二行的61220 处中断。
      猜你喜欢
      • 2023-03-05
      • 2012-06-20
      • 1970-01-01
      • 2018-10-20
      • 2023-01-30
      • 1970-01-01
      • 2021-02-08
      • 1970-01-01
      相关资源
      最近更新 更多