【问题标题】:Combine multiple lines between flags in one line in AWK在 AWK 中将标志之间的多行合并到一行中
【发布时间】:2021-03-21 21:26:42
【问题描述】:

示例文件:

Pattern 1

AAAAAAAAAA
BBBBBBBBBB

Pattern 2

我想在一行中打印文件中两个模式之间的行。 从上一个问题How to print lines between two patterns, inclusive or exclusive (in sed, AWK or Perl)? 我发现非常好

awk '/Pattern 1/{flag=1; next} /Pattern 2/{flag=0} flag' file

有输出:

AAAAAAAAAA
BBBBBBBBBB

我想要的输出:

AAAAAAAAAABBBBBBBBBB

【问题讨论】:

  • 如果Pattern1 存在但Pattern2 不存在应该怎么办?反之亦然?如果两者都在预期订单的 1 行怎么办?如果它们都以相反的顺序在 1 行上怎么办?如果两个分隔符之间的文本中间有一个空行怎么办?
  • 输入中是否可以多次出现Pattern 1 ... Pattern 2,如果是这样,您希望打印所有内容还是只打印第一个或最后一个或其他内容?
  • 在我(幸运)的情况下,模式总是一致的。
  • @anubhava 我该怎么做

标签: awk


【解决方案1】:

以这种方式让您的awk 程序在GNU awk 中编写和测试。

awk '
/Pattern 2/{
  if(found){
    print val
  }
  found=""
  next
}
/Pattern 1/{
  found=1
  next
}
found{
  val=val $0
}
'   Input_file

说明:为上述添加详细说明。

awk '                      ##Starting awk program from here.
/Pattern 2/{               ##Checking if Pattern 2 is found here then do following.
  if(found){               ##Checking if found is set then do following.
    print val              ##Printing val here.
  }
  found=""                 ##Nullifying found here.
  next                     ##next will skip all statements from here.
}
/Pattern 1/{               ##Checking if Pattern 1 is found in current line.
  found=1                  ##Setting found to 1 here.
  next                     ##next will skip all statements from here.
}
found{                     ##Checking condition if found is SET then do following.
  val=val $0               ##Creating val variable here which is keep adding current line values in it.
}
'  Input_file              ##Mentioning Input_file name here. 

【讨论】:

    【解决方案2】:

    你可以使用这个awk:

    awk '/Pattern 2/ {if (s!="") print s; s=f=""} f {s = s $0} /Pattern 1/ {f=1}' file
    
    AAAAAAAAAABBBBBBBBBB
    

    【讨论】:

    • Pattern 1 foo Pattern 1 bar Pattern 2 的情况下,将打印foobar,而my answer 将打印bar。 idk 是正确的,只是提到不同之处,因为提供的示例并未涵盖这种情况。
    • 是的,这是一个很好的观点,不确定哪个 OP 想要
    【解决方案3】:

    还有awk:

    awk -v RS= '!/Pattern/ {sub(/\n/,"");print}' file
    AAAAAAAAAABBBBBBBBBB
    

    【讨论】:

    • 我认为您不能假设 Pattern 1Pattern 2 共享一个公共子字符串 Pattern,我认为这些术语只是 OP 使用的 [坏] 示例,也不是它们不使用的示例' 不会出现在文本的其他地方,也不会总是按照打印所需的顺序(例如Pattern 2... Pattern 1)。
    • 好的。现在我明白了pattern 这个词是如何模棱两可的。
    【解决方案4】:

    使用用于多字符 RS 的 GNU awk 并假设您的“模式”确实占据了整行并且不能出现在您输入的其他地方(如果这是错误的,很容易修复):

    $ awk -v RS='Pattern 2' 'sub(/.*Pattern 1/,""){gsub(/\n/,""); print}' file
    AAAAAAAAAABBBBBBBBBB
    

    或使用任何 awk:

    awk 'f{ if (/Pattern 2/){print buf; f=0} else buf=buf $0 } /Pattern 1/{f=1; buf=""}' file
    AAAAAAAAAABBBBBBBBBB
    

    【讨论】:

      【解决方案5】:

      您可以使用-v ORS=将输出记录分隔符设置为空字符串:

      awk -v ORS= '/Pattern 1/{flag=1; next} /Pattern 2/{flag=0} flag' file
      

      an online demo

      要在末尾打印换行符,请添加END{print "\n"}

       awk -v ORS= '/Pattern 1/{flag=1; next} /Pattern 2/{flag=0} flag; END{print "\n"}' file > newfile
      

      查看 Ubuntu 18 屏幕截图:

      【讨论】:

      • 它将省略最后的尾随换行符,而不仅仅是在两者之间
      • 完全符合 OP 的要求,输出中没有换行符。 "我想在一行中打印文件中两个模式之间的行。"
      猜你喜欢
      • 2016-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多