如何在Unix中合并同一文本文件中的多行

时间:2013-05-08 07:19:44

标签: linux unix awk

我有一个文本文件,我想将这些行的内容放入一行。例如。

我有一个名为WEEE.txt的文本文件,它包含:

BSS100  PROF  K


BSS101  TREES E
BSS102  TRUNK R, S,
              V, R,
              T
BSS103  TEXT  KE
BSS104  WEEW  KER,
              SSS

我希望输出如下:

BSS100  PROF  K
BSS101  TREES E
BSS102  TRUNK R, S, V, R, T
BSS103  TEXT  KE
BSS104  WEEW  KER, SSS
但是,嘿。这是我目前正在进行的项目的一部分。这才是真实的!我引用顶部的第一个作为例子,但我不能这样做。 :) 请帮我! (据说这是BSC.txt)

BSC195






PROFILE             VDU0 , VDU1 , VDU2 , VDU3 , VDU4 , VDU5 ,
                    VDU6 , VDU7 , VDU8 , VDU9 , VDU10, VDU11,
                    VDU12, VDU13, VDU14, VDU15, CAL0 , VTP
MOKAS               NOKIA1
CBCERTCK            D10393
NUTRDM              NUPADM
SPMNGT              SPMNGT
NFTRA
RCCFVS              RCCMLA
TRAFAD              TRAFAD
NOCORF              NOCOSS
NETWCH              NETWCH
BSCOP5              BSCOPT
MMOPTI              MMOPTI
SYSSDE              SYSOP1
SMCSOC              SMCSOC
LRCCMM              ITNCCM
VENFVD              VENNSN
BSCGBF              BSCRHM
BSHGTD              BSCLOC, P10203
BSCASD              BSCEMR
LSCRIPT
BSCGVS              A13728, J02448, L13668, M14730, A12868, C11347,
                    L14203, C02285, A14419, B00797, S12666, M12653,
                    D04841, S02825, T14713, L15004, C01972, E12057,
                    S13319
LSNCMM              F02642
LSYSCRIPT           CATSYS

这就是我想要发生的事情:

BSC195






PROFILE             VDU0 , VDU1 , VDU2 , VDU3 , VDU4 , VDU5 ,VDU6 , VDU7 , VDU8 , VDU9 , VDU10, VDU11, VDU12, VDU13, VDU14, VDU15, CAL0 , VTP *
MOKAS               NOKIA1
CBCERTCK            D10393
NUTRDM              NUPADM
SPMNGT              SPMNGT
NFTRA
RCCFVS              RCCMLA
TRAFAD              TRAFAD
NOCORF              NOCOSS
NETWCH              NETWCH
BSCOP5              BSCOPT
MMOPTI              MMOPTI
SYSSDE              SYSOP1
SMCSOC              SMCSOC
LRCCMM              ITNCCM
VENFVD              VENNSN
BSCGBF              BSCRHM
BSHGTD              BSCLOC, P10203
BSCASD              BSCEMR
LSCRIPT
BSCGVS              A13728, J02448, L13668, M14730, A12868, C1198, L14203, C02285, A14419, B00797, S12666, M12653,D04841, S02825, T14713, L15004, C01972, E12057, S13319 *
LSNCMM              F02642
LSYSCRIPT           CATSYS

注意:*表示我想在一行上。从单个线路上的BSCGVS到S133319。以及在PROFILE中达到VTP。还有可能吗? 另一个注意:这只是我数据的一小部分。请帮忙。我不知道该怎么办。因为这将是我在数据库中的输入。 =)请帮助=)

5 个答案:

答案 0 :(得分:5)

sed ':a; N;/\n\S/! {s/\n */ /;ba}; P;D' WEEE.txt

答案 1 :(得分:1)

更新#2并改进我使解决方案过于复杂。这是简化的

如果您需要纯bash解决方案,请尝试上面的脚本。它仅使用内部bash函数,因此它不会调用任何外部程序(根本不会调用fork)。

while read; do
  #Skip empty lines
  [[ $REPLY =~ ^[[:space:]]*$ ]] && continue
  # Chomp all but one leading spaces
  [[ $REPLY =~ ^[[:space:]]+(.*) ]] && REPLY=" ${BASH_REMATCH[1]}"
  # Chomp trailing spaces
  [[ $REPLY =~ (.*[^[:space:]])[[:space:]]+$ ]] && REPLY="${BASH_REMATCH[1]}"
  echo -e "$REPLY\c"
  # Add LF at the end if not finished with ','
  [[ $REPLY =~ ,$ ]] || echo
done <<XXX
BSS100  PROF  K



BSS101  TREES E
BSS102  TRUNK R, S, 
              V, R,
              T
BSS103  TEXT  KE
BSS104  WEEW  KER,
              SSS
XXX

输出:

BSS100  PROF  K
BSS101  TREES E
BSS102  TRUNK R, S, V, R, T
BSS103  TEXT  KE
BSS104  WEEW  KER, SSS

做什么:

首先,文件被重定向到while循环。它比常用的cat file|while更好,因为它不会fork加倍cat一个,bash运行while循环的一个while ... done <filename。在这里,我使用“here-is-the-document”功能来制作更合理的例子。但您也可以使用while表单。

  • read循环处理文件中的所有行。如果REPLY没有进一步的arg,则将读取行放置到REPLY env var。
  • 然后检查REPLY是否包含(仅)零个或多个空格字符(空格或制表符)。如果是这样,循环继续。
  • 然后检查REPLY是否以一个或多个空格开头。如果是这样,多个空格被一个空格字符替换。
  • 然后检查REPLY是否以一个或多个空格结尾。如果是这样,则消除多个空白区域。
  • 然后打印REPLY时没有换行。
  • 然后检查,是否以{{1}}结尾。如果不是这样,那么换行就是打印机。

    参考文献:bash(1)regex(7)fork(2)

  • 答案 2 :(得分:1)

    这应该可以解决问题:

    awk '/^BS/{printf "%s%s ",s,$0;s="\n";next}{sub(/^\s*/,"");printf "%s ",$0}' file
    BSS100  PROF  K
    BSS101  TREES E
    BSS102  TRUNK R, S, V, R, T
    BSS103  TEXT  KE
    BSS104  WEEW  KER, SSS
    

    答案 3 :(得分:1)

    awk '/^\S/{printf "%s%s",rs,$0; rs="\n"; next} {$1=" "$1;printf "%s",$0} END{print ""}' file
    

    当您的输入文件执行并且不以BS启动的行结束时尝试:

    $ cat file
    BSS100  PROF  K
    BSS101  TREES E
    BSS102  TRUNK R, S,
                  V, R,
                  T
    BSS103  TEXT  KE
    BSS104  WEEW  KER,
                  SSS
    $
    $ awk '/^\S/{printf "%s%s",rs,$0; rs="\n"; next} {$1=" "$1;printf "%s",$0} END{print ""}' file
    BSS100  PROF  K
    BSS101  TREES E
    BSS102  TRUNK R, S, V, R, T
    BSS103  TEXT  KE
    BSS104  WEEW  KER, SSS
    $
    $ cat file1
    BSS100  PROF  K
    BSS101  TREES E
    BSS102  TRUNK R, S,
                  V, R,
                  T
    BSS103  TEXT  KE
    BSS104  WEEW  KER,
                  SSS
    BSS104  WEEW  FOO
    $
    $ awk '/^\S/{printf "%s%s",rs,$0; rs="\n"; next} {$1=" "$1;printf "%s",$0} END{print ""}' file1
    BSS100  PROF  K
    BSS101  TREES E
    BSS102  TRUNK R, S, V, R, T
    BSS103  TEXT  KE
    BSS104  WEEW  KER, SSS
    BSS104  WEEW  FOO
    

    答案 4 :(得分:0)

    我不擅长awk,但无论如何:

    >awk '/^BSS/ {if (NR>1) printf("\n"); printf("%s", $0);} !/^BSS/ {printf(", %s", $1); } END {printf("\n");} ' WEEE.txt
    BSS100   K
    BSS101   E
    BSS102   R, V, S
    BSS103   KE
    BSS104   KER, SSS
    

    <强>更新

    >awk '/^BSS/ {if (NR>1) printf("\n"); for(i=3;i<=NF;i++) gsub(",$", "", $i);  printf("%s %s %s", $1, $2, $3);  for(i=4;i<=NF;i++) printf(", %s", $i); } !/^BSS/ { for(i=1;i<=NF;i++) {gsub(",$", "", $i); printf(", %s", $i);}  }END {printf("\n");}  ' WEEE.txt
    BSS100 PROF K
    BSS101 TREES E
    BSS102 TRUNK R, S, V, R, T
    BSS103 TEXT KE
    BSS104 WEEW KER, SSS