使用 sed 连接表中的行

使用 sed 连接表中的行

我的查询中有下表,+但我的分隔符是在“描述”下创建新行,如下例所示:


TYPE+DESCRIPTION+PRIORITY+DATE
1+text1+HIGH+Aug 15
+text2  
2+text+LOW+Aug 11
3+text+LOW+Aug 11
4+text1+HIGH+Aug 15
+text2  
+text3

我如何使用 sed 让它看起来像下面这样

TYPE    DESCRIPTION      PRIORITY DATE
1       text1 text2      HIGH     Aug 15
2       text             LOW      Aug 11
3       text             LOW      Aug 11
4       text text2 text3 HIGH     Aug 15

我努力了:

sed -n '1{h;n};/^ *+ */{s// /;H;n};{x;s/\n//g;p};${x;p}' 

但给了我错误(sed:命令乱码),谢谢

答案1

awk '
    BEGIN{OFS=FS="+"}
    {sub(/[[:blank:]]+$/,"")}  #Removes trailing blanks
    NF==4{print line;line=$0}
    NF==2{x=$2;$0=line;$2=$2" "x;line=$0}
    END{print line}
' file | column -ts "+"

其背后的主要思想是 if NF==2, then 将第二个字段放入$2前一行的第二个字段中。所以发生的事情是

1+text1+HIGH+Aug 15 #Puts this in "line" variable
+text2              #Transfer 2nd field to "line" second field
# Resulting in...
1+text1 text2+High+Aug 15

column+从输出中删除来生成这个精细的最终输出:

TYPE  DESCRIPTION        PRIORITY  DATE
1     text1 text2        HIGH      Aug 15
2     text               LOW       Aug 11
3     text               LOW       Aug 11
4     text1 text2 text3  HIGH      Aug 15

答案2

打造“领域不可知论”awk

tac file | awk 'BEGIN{FS="+"}
    {flds=(NF>flds)?NF:flds;for (i=1; i<=NF; i++) {f=(length($i)>0)?gensub(/ +$/,"","g",$i)" ":"";fld[i]=f fld[i]}}
    $1>0{for (i=1; i<=flds; i++) printf fld[i]"+"; printf "\n"; delete fld}' | 
    tac | column -ts "+"

TYPE   DESCRIPTION         PRIORITY   DATE     
1      text1 text2         HIGH       Aug 15   
2      text                LOW        Aug 11   
3      text                LOW        Aug 11   
4      text1 text2 text3   HIGH       Aug 15  

演练

翻转文件,以便当 $1 不为空并设置时就知道是时候打印了FS

tac file | awk 'BEGIN{FS="+"}

计算最大数量flds,循环遍历字段,修剪它们并检查空白,按字段将它们加载到数组中以聚合它们

    {flds=(NF>flds)?NF:flds;for (i=1; i<=NF; i++) {f=(length($i)>0)?gensub(/ +$/,"","g",$i)" ":"";fld[i]=f fld[i]}}

如果$1非空则输出该行并重置数组

    $1>0{for (i=1; i<=flds; i++) printf fld[i]"+"; printf "\n"; delete fld}' | 

通过管道tac将其翻转并用于column美化它

    tac | column -ts "+"

编辑

真的不喜欢第二个循环,gensub当你可以sed在管道中用锤子敲击它时停止到每个字段,并且可以简化测试。感觉不优雅。

所以这里有一个打高尔夫球版本只是感觉对我更好:

tac file | awk 'BEGIN{FS="+"}
    {flds=(NF>flds)?NF:flds;
        for (i=1; i<=NF; i++) {fld[i]=$i" "fld[i];
        if ($1) printf fld[i]"+"}}
    $1{ printf "\n"; delete fld}' |
    sed -E "s/  +/ /g" | tac | column -ts "+" 

答案3

返回并阅读我们的 sed 版本之间可能存在的差异,并从头开始重写它。希望这有效:

:r
    $!N
    y:+:,:
    /\n,/{
        s:^\([^,]\{1,\},[^,]\{1,\}\)\([^\n]\{1,\}\)\n,\([^ \n]\{1,\}\).*$:\1 \3\2:
        br
    }
    $!P
    $!D

输出:

TYPE,DESCRIPTION,PRIORITY,DATE
1,text1 text2,HIGH,Aug 15
2,text,LOW,Aug 11
3,text,LOW,Aug 11
4,text1 text2 text3,HIGH,Aug 15

答案4

perl -0pe 'while(s/(.*?)\+(.*?)\+(.*)\n\+(.*)/$1+$2 $4+$3/g){}' file
  • perl -0 - 吞掉所有输入
  • s/(.*?)\+(.*?)\+(.*)\n\+(.*)/$1+$2 $4+$3/gA+B+...C\n+D在可能的情况下进行转变A+B D+...C

相关内容