用awk /或/ sed bash条件getline?

问题描述 投票:4回答:5

我正在努力解决这个问题,我希望将一组行连接成一行/一行。我文件的每一行(titi / toto / tata)有2或3个以“;”分隔的字段所以我的输入是这样的:

titi1
titi2 
titi3
43;75;97
1;2;87
toto1
toto2
toto3
40;50;60
tata1
tata2
tata3
4;5;2
5;3;7
2;5;9

我需要这个输出:

titi1;titi2;titi3;43;75;97
titi1;titi2;titi3;1;2;87
toto1;toto2;toto3;40;50;60
tata1;tata2;tata3;4;5;2
tata1;tata2;tata3;5;3;7
tata1;tata2;tata3;2;5;9

那么你可以看到前3行是信息(toto / tata等...),应该在数字开始后为每一行重复这些信息。

首先,我的输入只有一行数字,所以它是一个4乘4的分组。所以我在论坛搜索了我找到了一个例子并用这样的getline做了这个:

awk '{getline b; getline c; getline d;printf("%s %s %s %s\n",$0,b,c,d)}'

但后来我开始有2个甚至3个数字... ...所以我正在努力做一个“条件”,理解它应该重复前3个lign每次它看到一个从数字开始的lign。

bash awk sed tr
5个回答
1
投票

该计划应如此:

awk 'f&&/^[^0-9]/{b="";f=0} /^[^0-9]/{b=b$0";"} /^[0-9]/{print b$0;f=1}'

说明:

  1. /^[^0-9]/{b=b$0";"}
  2. /^[0-9]/{print b$0;f=1}
  3. f&&/^[^0-9]/{b="";f=0}
  1. 行不以数字开头:收集输入(titi,toto,tata)
  2. 行以数字开头:打印收集的行和$0,设置标志
  3. line不再以数字开头(标志已设置):重新开始(清除缓冲区和标志)

2
投票

你可以尝试一下吗?

awk '
{
  sub(/ +$/,"")
}
/^[a-zA-Z]+/{
  if(val && flag){
    val=""
  }
  val=val?val ";" $0:$0
  flag=""
  next
}
{
  flag=1
  print val ";" $0
}'  Input_file

解决方案第二:如果您的Input_file可以将最后一行作为tot等,并且您也想要打印它,那么请使用以下内容。

awk '
{
  sub(/ +$/,"")
}
/^[a-zA-Z]+/{
  if(val && flag){
     val=""
  }
  val=val?val ";" $0:$0
  flag=""
  next
}
{
  flag=1
  print val ";" $0
}
END{
  if(val && !flag){
     print val
  }
}'  Input_file

2
投票
$ awk -F';' 'NF>1{print s $0; p=1; next} p{s=p=""} {s=s $0 FS}' file
titi1;titi2;titi3;43;75;97
titi1;titi2;titi3;1;2;87
toto1;toto2;toto3;40;50;60
tata1;tata2;tata3;4;5;2
tata1;tata2;tata3;5;3;7
tata1;tata2;tata3;2;5;9

你的原始剧本 - 请参阅http://awk.freeshell.org/AllAboutGetline,了解为什么不使用getline(或大多数其他情况)以及如何在适当的情况下在极少数情况下正确调用getline。


1
投票

你可以尝试这个awk:

awk -F';' 'NF==1{if(b){a=b=""};a=a$0FS;next}{b=1;$0=a$0}1' infile

而且更容易理解

awk -F ';' '
  NF==1 {
    if ( b ) {
      a = b = "" 
    }
    a = a $0 FS 
    next
  }
  {
    b = 1
    $0 = a $0
  } 1
' infile

1
投票

这可能适合你(GNU sed):

sed -r '/;/{:a;G;s/([^\n]*)\n(.*)/\2\n\1/;s/.//;s/\s*\n/;/g;n;/;/ba;x;z;x};H;d' file

使用保留空间存储每条记录的第一部分。遇到记录的结尾部分时,追加保留空间,重新排列最后一部分以跟随第一部分,删除第一个换行符并用分号替换剩余的换行符。打印记录,如果下一行是记录重复的结尾部分。否则,清除保留空间并将当前行附加到保留空间。

© www.soinside.com 2019 - 2024. All rights reserved.