shell awk:源代码行1处的非法语句

ffdz8vbo  于 2023-08-07  发布在  Shell
关注(0)|答案(2)|浏览(110)

我有一个巨大的XML文件,我想分裂的基础上,最少的记录,即元素。每个拆分文件100。
在这个例子中,xml只有两条记录,所以awk应该为每个stuRec创建一个xml文件,因为我把最小文件数硬编码为1。
但我得到了错误:“awk:illegal statement at source line 1”我不知道如何修复这个错误。

<?xml version="1.0"?>
<studentData>
<stuRec>
 <as>
 <sourceSys>BBC</sourceSys>
 <acctDt>2023-04-04</acctDt>
 </as>
 <stats>
 <ss>
  <prov>AB</prov>
  <cono>1</cono>
 </ss>
 </stats> 
</stuRec>
<stuRec>
 <as>
 <sourceSys>RCD</sourceSys>
 <acctDt>2023-05-14</acctDt>
 </as>
 <stats>
 <ss>
  <prov>ON</prov>
  <cono>2</cono>
 </ss>
 </stats> 
</stuRec>
</studentData>

awk -v element="stuRec" ' BEGIN { n =1; i = 1} /<\// && $0 ~ "</" element ">" { n++; } {print $0 > "output/part_" i ".xml"; if (n % 1 = 0) { i++; } }' "student_records.xml"

字符串

vfwfrxfs

vfwfrxfs1#

awk是处理XML时使用的错误工具;你需要一些真正理解格式的东西,比如令人难以置信的方便的xmlstarlet。一个示例脚本,首先使用它来查找文档中stuRec节点的数量,然后循环,生成每个节点中具有给定数量的新XML文件:

#!/usr/bin/env bash

# Usage:
# ./split.sh input.xml output-dir [step-size]

xmlfile=$1
outputdir=$2
# Default to 100 elements at a time
declare -i step=${3:-100}

# First, find the number of stuRec nodes
declare -i nodes
nodes=$(xmlstarlet sel -T -t -v 'count(/studentData/stuRec)' "$xmlfile")

#printf "There are %d stuRec nodes\n" $nodes

# Now step through $step at a time, creating a new XML document with just the
# records in that range:

declare -i fileno=1
mkdir -p "$outputdir"

for (( i = 1; i <= nodes; i += step)); do
    # Delete all the stuRec nodes outside of a given position range
    xmlstarlet edit -d "/studentData/stuRec[not(position() >= $i and position() < $i + $step)]" "$xmlfile" > "output/part_${fileno}.xml"
    fileno+=1
done

字符串
既然你说这是一个大文件,下面是一个perl脚本,它使用XML::Twig模块(使用你的操作系统的包管理器或最喜欢的CPAN客户端安装)来读取XML文档一次(并且不必在内存中保存整个解析的文档;它的目的是为了有效地处理非常大的XML文件):

#!/usr/bin/env perl
# Usage: split.pl [--step=N] input.xml output-dir
use strict;
use warnings;
use feature qw/say state/;
use XML::Twig;
use Getopt::Long;

my $step = 100;
GetOptions("step=i" => \$step)
    or die "Error in command line arguments\n";

die "Usage: $0 [--step=N] input.xml output-directory\n" unless @ARGV == 2;
my ($xmlfile, $outputdir) = @ARGV;

mkdir $outputdir;

my $xml = XML::Twig->new(
    twig_handlers => {
        stuRec => sub { handle_records(0, @_) },
        # Used to catch the last block of records
        studentData => sub { handle_records(1, @_) }
    },
    pretty_print => 'indented'
    );
$xml->parsefile($xmlfile);

sub handle_records {
    state $fileno = 1;
    state $records = 0;
    my ($last, $twig, $elt) = @_;
    if ($last || ++$records == $step) {
        my $partname = "${outputdir}/part_${fileno}.xml";
        # say "Creating $partname";
        $twig->print_to_file($partname);
        $twig->purge;
        $records = 0;
        $fileno += 1;
    }
    return 1;
}

qnakjoqk

qnakjoqk2#

假设条件:

  • 输入文件的格式与示例中的格式相同(例如,文件的全部内容不驻留在一行中)
  • 第一个<stuRec>之前的行(称为“头”)和最后一个</stuRec>之后的行(称为“尾”)将被写入每个输出文件

一个awk的想法,将 * 每个 * stuRec块写入 * 单独的 * 文件:

awk -v element="stuRec" '
BEGIN                          { find_hdr = 1; find_tail = 0 }
$0 ~ "<" element ">"           { find_hdr = find_tail = 0
                                 n++
                                 fname[n] = "output/part_" n ".xml"
                                 print hdr > fname[n]
                               }
find_hdr                       { hdr  = hdr  (hdr  == "" ? "" : ORS) $0; next }
find_tail                      { tail = tail (tail == "" ? "" : ORS) $0; next }
fname[n]                       { print $0 > fname[n] }
$0 ~ "</" element ">"          { close(fname[n]); find_tail = 1 }
END                            { for (i=1; i<=n; i++) {
                                     print tail >> fname[i]
                                     close(fname[i])
                                 }
                               }
' "student_records.xml"

字符串
这产生:

$ head -20 output/part*xml
==> output/part_1.xml <==
<?xml version="1.0"?>
<stuRec>
 <as>
 <sourceSys>BBC</sourceSys>
 <acctDt>2023-04-04</acctDt>
 </as>
 <stats>
 <ss>
  <prov>AB</prov>
  <cono>1</cono>
 </ss>
 </stats>
</stuRec>
</studentData>

==> output/part_2.xml <==
<?xml version="1.0"?>
<stuRec>
 <as>
 <sourceSys>RCD</sourceSys>
 <acctDt>2023-05-14</acctDt>
 </as>
 <stats>
 <ss>
  <prov>ON</prov>
  <cono>2</cono>
 </ss>
 </stats>
</stuRec>
</studentData>

注意事项:

  • 要将X>1数量的stuRec块放入单个文件中,OP应该能够添加额外的计数器,并使用它来确定何时递增n(从而创建新的输出文件)
  • 如果OP在运行X>1解决方案时遇到问题,那么我建议问一个新的问题,确保提供尝试的代码

相关问题