Shell 多个分隔符行的AWK拆分

Shell 多个分隔符行的AWK拆分,shell,unix,awk,split,Shell,Unix,Awk,Split,我正在尝试使用AWK一行分割一个文件,但下面的代码无法正常工作 awk ' BEGIN { idx=0; file="original_file.split." } /^REC_DELIMITER.(HIGH|TOP)$/ { idx++ } /^REC_DELIMITER.TOP$/,/^REC_DELIMITER.(HIGH|TOP)$/ { print > file sprintf("%03d", idx) } ' original_file 测试文件为“原始文件”: 上面的AWK

我正在尝试使用AWK一行分割一个文件,但下面的代码无法正常工作

awk '
BEGIN { idx=0; file="original_file.split." }
/^REC_DELIMITER.(HIGH|TOP)$/ { idx++ }
/^REC_DELIMITER.TOP$/,/^REC_DELIMITER.(HIGH|TOP)$/ { print > file sprintf("%03d", idx) }
' original_file
测试文件为“原始文件”:

上面的AWK代码用于REC_DELIMITER.TOP,它为我提供了以下文件:

original_file.split.001:
REC_DELIMITER.TOP

original_file.split.003:
REC_DELIMITER.TOP
然而,我正试图做到这一点:

original_file.split.001:
REC_DELIMITER.TOP
lineA1
lineA2
lineA3

original_file.split.003:
REC_DELIMITER.TOP
lineC1
lineC2
lineC3
将有其他记录分隔符,需要时,我们可以为它们运行REC_DELIMITER.HIGH,这样可以获得如下文件:

original_file.split.002:
REC_DELIMITER.HIGH
lineB1
lineB2
lineB3

original_file.split.004:
REC_DELIMITER.HIGH
lineD1
lineD2
lineD3
任何帮助都是非常感谢的,我在过去的几天里一直在努力让这个工作,上面的AWK代码是我能得到的最好的。我现在需要AWK大师的帮助。:)


谢谢大家!

您可以尝试以下方法:

awk '
/REC_DELIMITER\.TOP/ {
    a=1
    b=0
    file = sprintf (FILENAME".split.%03d",++n)
}    
/REC_DELIMITER\.HIGH/ {
    b=1
    a=0
    file = sprintf (FILENAME".split.%03d",++n)
}  
a {
    print $0 > file
}    
b {
    print $0 > file
}' file

您需要这样的东西(未经测试):


我做了一些更改,使不同的分隔符可以转到它们自己的文件中,即使它们稍后出现在文件中。使用下面的内容创建一个类似splitter.awk的文件,chmod+x将其保存并使用
/splitter.awk original_文件运行它

#!/usr/bin/awk -f
BEGIN {
  idx=0;
  file="original_file.split.";
  out=""
}
{
  if($0 ~ /^REC_DELIMITER.(TOP|HIGH)/){
    if (!cnt[$0]) {
      cnt[$0] = ++idx;
    }
    out=cnt[$0];
  }
  print >  file sprintf("%03d", out)
}
(在末尾加上或加上一个换行符。)

一般来说,当输入被视为一系列多行记录,并以一个特殊的行作为分隔符时,最直接的方法是将分隔符(通常是分隔符)设置为该分隔符

通常情况下,您希望在其开头和/或结尾添加换行符,但这种情况有点特殊,因此没有换行符会更容易


编辑以添加:您需要GNU Awk来完成此操作。标准Awk只考虑RS的第一个字符。

我不太习惯Awk,然而,plasticide的回答让我朝着正确的方向前进,我最终得到了符合要求的Awk脚本

在下面的代码中,如果发现除雾器,首先将echo设置为0。第二,如果将echo设置为1,如果找到所需的分隔符,则从文件中分割所需的分隔符

我知道regex可以是类似于
/^(REC|u(DELIMITER\(TOP | HIGH | LOW)| NO_CATEGORY)$/
的东西,但由于regex是通过shellscript动态创建的,shellscript从特定文件中读取分隔符列表,因此它看起来更像下面的AWK

awk 'BEGIN {
  idx=0; echo=1; file="original_file.split."
}
{
  #All the delimiters to consider in given file
  if($0 ~ /^(REC_DELIMITER.TOP|REC_DELIMITER.HIGH|REC_DELIMITER.LOW|REC_NO_CATEGORY)$/) {
    echo=0
  }
  #Delimiters that should actually be pulled
  if($0 ~ /^(REC_DELIMITER.HIGH|REC_DELIMITER.LOW)$/ {
    idx++; echo=1
  }
  #Print to a file is match wanted delimmiter
  if(echo) {
    print > file idx
  }
}' original_file

谢谢大家。我真的非常感谢。

将4行代码塞进一行对可读性没有帮助。另外,从示例输入/输出中删除HTML,除非它确实存在于您的文件中。谢谢..删除了HTML。这个建议的解决方案真的很酷,但不幸的是,我不能使用dbase=“^REC_DELIMITER\\。分隔符应该会更改…只有文件结构不会更改。因此会有具有不同分隔符的文件。然后只需使用-v显式设置“delim”,而不是从部分构建它。但是如果分隔符可以是任何内容,您如何知道行何时包含分隔符?我的意思是,如果您正在搜索“REC_DELIMITER.TOP”并找到文本“REC_DELIMITER.HIGH”,如何将其与不包含“REC_DELIMITER.TOP”的任何其他行区分开来"?分隔符是从另一个文件中读取的。根据正在处理的内容。这就是它可以是任何东西的原因。我终于让它按预期工作。谢谢你的帮助。我很感激!谢谢!你的回答让我朝着正确的方向前进,我终于让AWK脚本按要求工作。你觉得不接受答案有点刻薄吗你的解决方案基于。
#!/usr/bin/awk -f
BEGIN {
  idx=0;
  file="original_file.split.";
  out=""
}
{
  if($0 ~ /^REC_DELIMITER.(TOP|HIGH)/){
    if (!cnt[$0]) {
      cnt[$0] = ++idx;
    }
    out=cnt[$0];
  }
  print >  file sprintf("%03d", out)
}
awk -vRS=REC_DELIMITER '/^.TOP\n/{print RS $0 > sprintf("original_file.split.%03d",n)};!++n' original_file
awk 'BEGIN {
  idx=0; echo=1; file="original_file.split."
}
{
  #All the delimiters to consider in given file
  if($0 ~ /^(REC_DELIMITER.TOP|REC_DELIMITER.HIGH|REC_DELIMITER.LOW|REC_NO_CATEGORY)$/) {
    echo=0
  }
  #Delimiters that should actually be pulled
  if($0 ~ /^(REC_DELIMITER.HIGH|REC_DELIMITER.LOW)$/ {
    idx++; echo=1
  }
  #Print to a file is match wanted delimmiter
  if(echo) {
    print > file idx
  }
}' original_file