3

我正在尝试使用 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

测试文件是“original_file”:

REC_DELIMITER.TOP
lineA1
lineA2
lineA3
REC_DELIMITER.HIGH
lineB1
lineB2
lineB3
REC_DELIMITER.TOP
lineC1
lineC2
lineC3
REC_DELIMITER.HIGH
lineD1
lineD2
lineD3

上面的 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 大师的帮助。:)

谢谢!

4

5 回答 5

5

你可以尝试这样的事情:

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
于 2013-06-11T20:04:25.407 回答
3

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

awk -v dtype="TOP" '
BEGIN { dbase = "^REC_DELIMITER\\."; delim = dbase dtype "$" }
$0 ~ dbase { inBlock=0 }
$0 ~ delim { inBlock=1; idx++ }
inBlock { print > sprintf("original_file.split.%03d", idx) }
' original_file
于 2013-06-11T20:05:03.547 回答
2
awk -vRS=REC_DELIMITER '/^.TOP\n/{print RS $0 > sprintf("original_file.split.%03d",n)};!++n' original_file

(在最后给出或采取额外的换行符。)

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

通常你会想在它的开头和/或结尾添加换行符,但这种情况有点特殊,所以没有它们会更容易。

编辑添加:为此,您需要 GNU Awk。标准 awk 只考虑 RS 的第一个字符。

于 2013-06-12T01:16:19.463 回答
1

我做了一些更改,以便不同的分隔符转到他们自己的文件,即使它们稍后出现在文件中。制作一个像 splitter.awk 这样的文件,内容如下, chmod +x 它并运行它./splitter.awk original_file

#!/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)
}
于 2013-06-11T20:18:48.090 回答
-2

我不太习惯 AWK,但是,plasticide 的回答让我朝着正确的方向前进,我终于让 AWK 脚本按要求工作。

在下面的代码中,如果找到 demilier,则首先 IF 将 echo 转为 0。如果找到想要的分隔符,则第二个 IF 将 echo 变为 1,然后从文件中拆分出想要的分隔符。

我知道正则表达式可能类似于,/^(REC_(DELIMITER\.(TOP|HIGH|LOW)|NO_CATEGORY)$/但由于正则表达式是通过从特定文件读取分隔符列表的 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

谢谢你们。我真的非常感谢。

于 2013-06-17T18:02:06.217 回答