【问题标题】:bash conditionnal getline with awk/tr/sed?使用awk/或/sed bash 条件getline?
【发布时间】:2019-02-20 14:48:42
【问题描述】:

我正在为此苦苦挣扎,我想将一组行连接成一行/一行。 我的文件的每一行 (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 x 4 的分组。所以我在论坛中搜索了我是否找到了一个示例并使用这样的 getline 做到了这一点:

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

但后来我开始有 2 甚至 3 与数字对齐... 所以我正在努力做一个“条件”,它明白每次看到以数字开头的 lign 时它都应该重复前 3 lign。

【问题讨论】:

  • 谢谢,我马上去看看。

标签: bash awk sed tr


【解决方案1】:

请您尝试关注一下。

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

解决方案 2: 如果您的 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
    

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

    【讨论】:

      【解决方案3】:

      这个程序应该这样:

      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. 行不再以数字开头(标志已设置):重新开始(清除缓冲区和标志)

      【讨论】:

        【解决方案4】:

        你可以试试这个 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
        

        【讨论】:

          【解决方案5】:

          这可能对你有用(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
          

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-05-01
            • 2013-11-09
            • 2019-12-23
            • 2017-04-23
            • 2015-03-19
            • 2015-06-16
            • 2018-03-31
            相关资源
            最近更新 更多